<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Gubatron.com</title>
	<atom:link href="https://www.gubatron.com/blog/feed/" rel="self" type="application/rss+xml"/>
	<link>https://www.gubatron.com/blog</link>
	<description>Personal Coding and Hobby Notebook</description>
	<lastBuildDate>Mon, 09 Mar 2026 17:37:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">87318645</site>	<itunes:explicit>no</itunes:explicit><itunes:subtitle>Personal Coding and Hobby Notebook</itunes:subtitle><item>
		<title>Agentes, Automatización y el Futuro de los Medios</title>
		<link>https://www.gubatron.com/blog/agentes-automatizacion-y-el-futuro-de-los-medios/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Mon, 09 Mar 2026 17:36:58 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4184</guid>

					<description><![CDATA[Explico cómo converti una publicación sobre Bitcoin en una operación editorial fuertemente automatizada con modelos de IA, flujos agenticos y herramientas desarrolladas en Rust. Su relato no solo describe un salto de 20 a 80 artículos diarios, sino que también plantea una idea más ambiciosa: usar blockchain como memoria persistente para agentes de inteligencia artificial. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Explico cómo converti una publicación sobre Bitcoin en una operación editorial fuertemente automatizada con modelos de IA, flujos agenticos y herramientas desarrolladas en Rust. Su relato no solo describe un salto de 20 a 80 artículos diarios, sino que también plantea una idea más ambiciosa: usar blockchain como memoria persistente para agentes de inteligencia artificial.<br />
***</strong></p>
<ul>
<li><strong>Angel Leon afirmó que su operación editorial pasó de producir unas 20 notas diarias a cerca de 80 gracias a la automatización con IA.</strong></li>
<li><strong>El sistema integra scraping, redacción, generación de imágenes, SEO, categorización y carga automática de borradores en WordPress.</strong></li>
<li><strong>Como siguiente paso, propuso una “Thought Chain”, una cadena de bloques para almacenar recuerdos, lecciones y decisiones de agentes de IA.</strong></li>
</ul>
<p>&nbsp;</p>
<hr />
<p>La convergencia entre inteligencia artificial, automatización editorial y blockchain ya no se limita a experimentos de laboratorio. En el sector de medios especializados, estas tecnologías comienzan a combinarse en sistemas capaces de traducir, redactar, clasificar, ilustrar y publicar contenido con una intervención humana cada vez menor.</p>
<p>Ese fue el eje de la exposición <em>Building an AI Newsroom: <a href="https://www.youtube.com/watch?v=ylVP4EGvT8M">Agents, Automation, and the Future of Media</a></em>, Allí relaté cómo evolucionó la operación de DiarioBitcoin desde una pequeña publicación enfocada en lectores hispanohablantes hasta una estructura con flujos casi completamente automatizados.</p>
<p>Lejos de presentar un marco teórico cerrado, Leon describió una secuencia de pruebas, ajustes y herramientas construidas sobre la marcha. Según explicó, el objetivo no era diseñar un sistema perfecto desde el inicio, sino resolver problemas concretos de producción y escalar gradualmente una sala de redacción especializada en noticias sobre Bitcoin y el ecosistema cripto.</p>
<p>El trasfondo de esa historia tiene peso dentro del sector. Los medios cripto suelen operar en un entorno de alta velocidad, con abundancia de fuentes en inglés, movimientos de mercado constantes y una audiencia que exige cobertura continua. En ese contexto, reducir tiempos de procesamiento sin perder consistencia editorial puede convertirse en una ventaja competitiva clave.</p>
<h2>De un equipo humano de traducción a una operación asistida por modelos</h2>
<p>Leon recordó que el proyecto comenzó en 2014 como una iniciativa personal, nacida de su interés por compartir en español información sobre Bitcoin que originalmente encontraba en inglés. Con el tiempo, esa actividad dejó de ser un blog personal y se convirtió en una publicación con anunciantes y un equipo de trabajo más formal.</p>
<p>Según su relato, la estructura llegó a incluir cinco personas de base: él mismo, una persona de ventas, una editora premiada exiliada de Venezuela y dos redactoras jóvenes, una formada en psicología que derivó al blogging y otra egresada de literatura que había sido alumna de la editora. Además, existía una red de colaboradores externos pagados por pieza, con montos de entre USD $2 y USD $4 por publicación.</p>
<p>En esa etapa, gran parte del trabajo consistía en traducir contenido, aunque más tarde también se incorporaron notas originales. Sin embargo, la demanda informativa era tan alta que la publicación dependía de tareas repetitivas y mano de obra adicional para sostener el ritmo de cobertura.</p>
<p>La llegada de GPT-3.5 abrió una primera etapa de experimentación. Leon dijo que comenzó copiando y pegando textos para probar las capacidades de traducción y para intentar trasladar al modelo el estilo editorial aprendido con su editora. Los resultados mostraban potencial, pero seguían siendo inconsistentes y no lograban convencer al equipo responsable de la edición.</p>
<p>El panorama cambió con las primeras versiones de GPT-4. A partir de allí, explicó, la calidad mejoró lo suficiente como para pasar del uso manual al consumo vía API. Ese salto permitió integrar el modelo a herramientas propias y convertir tareas editoriales repetitivas en procesos automatizados con intervención programática.</p>
<h2>Rust, bots y comandos: la arquitectura de una redacción automatizada</h2>
<p>Leon indicó que su entorno de desarrollo está basado principalmente en Rust, mientras que PHP solo se utiliza cuando es indispensable interactuar con WordPress. Sobre esa base construyó un wrapper ligero para conectarse a distintos modelos de lenguaje desde una única capa, sin depender de un solo proveedor.</p>
<p>Esa abstracción le permitió alternar entre GPT, Claude, Grok y otras opciones según el tipo de tarea. En su explicación, Grok era especialmente útil para consultas sobre noticias en tiempo real y movimientos de precios, mientras que GPT seguía destacando en la redacción de artículos.</p>
<p>Encima de esa infraestructura, desarrolló un bot capaz de recibir órdenes tanto en Slack como en Telegram, convirtiendo esos canales en una suerte de línea de comandos para la redacción. Algunas instrucciones ejecutan tareas determinísticas, mientras que otras invocan modelos de IA cuando se necesita razonamiento o generación de texto.</p>
<p>El comando central del sistema es <em>draft</em>. Su función es tomar una o varias URL, archivos PDF o incluso videos, extraer la información relevante y producir un borrador listo para publicarse en el sitio. Para alimentar ese flujo, Leon construyó otra herramienta llamada Uni News, descrita como un scraper de artículos impulsado por IA.</p>
<p>Uni News, según detalló, puede recuperar título, autor, fecha de publicación y contenido principal en un formato normalizado, ya sea Markdown o JSON. Si el recurso es accesible y no está protegido por bloqueos severos, el sistema procesa HTML, texto u otros formatos y los prepara para que el backend en Rust genere la nota.</p>
<p>Una vez obtenida la información, el modelo redacta el artículo siguiendo pautas editoriales. Leon afirmó que las versiones más recientes ya obedecen con precisión ese conjunto de instrucciones, un punto que había sido problemático en las primeras etapas, cuando las respuestas omitían enlaces, categorías o detalles de formato.</p>
<h2>Imágenes, SEO y WordPress: el flujo completo de publicación</h2>
<p>La automatización no se detiene en la redacción. De acuerdo con Leon, el mismo flujo genera también un prompt para crear una imagen original relacionada con la nota. Esa instrucción se envía luego a un modelo de imágenes, con Grok Imagine como una de las herramientas usadas con mayor frecuencia.</p>
<p>Este cambio eliminó otro dolor operativo frecuente en los medios digitales: la búsqueda de imágenes libres de derechos. Leon sostuvo que la generación propia redujo el riesgo de disputas por propiedad intelectual, una preocupación recurrente para publicaciones que deben ilustrar muchas notas cada día.</p>
<p>En paralelo, el backend se comunica con WordPress vía REST para crear un borrador, asignarle categorías y completar campos de SEO. El sistema, dijo, identifica automáticamente en qué secciones encaja la nota, algo que antes dependía del criterio del editor y a veces se ejecutaba de forma inconsistente.</p>
<p>Después, una herramienta adicional redimensiona y comprime la imagen para asegurar cargas rápidas. El archivo se sube al gestor de contenidos y queda asociado al borrador. En la práctica, el proceso deja un artículo casi terminado, de modo que la tarea humana se limita a abrirlo y pulsar publicar.</p>
<p>Leon añadió que recientemente incorporó una función para revisar las 25 publicaciones anteriores y detectar si la nueva pieza repite un tema ya cubierto. Ese filtro ayuda a evitar duplicaciones cuando la producción crece y varios procesos o personas trabajan en paralelo sobre noticias similares.</p>
<h2>De 20 a 80 artículos diarios y el objetivo de operar 24/7</h2>
<p>Las cifras ofrecidas por Leon muestran el alcance del cambio. Antes de la automatización, la publicación generaba cerca de 20 artículos diarios en una jornada buena. Con la nueva estructura, dijo, el ritmo subió con facilidad a 80 notas al día, con un potencial superior a 96.</p>
<p>Ese aumento no proviene solamente de ahorrar costos laborales. En su visión, la ventaja central es convertir una publicación relativamente pequeña en una operación mucho más amplia, capaz de cubrir más podcasts, más documentos y más eventos del ecosistema en lapsos muy cortos.</p>
<p>La automatización también se extiende a la distribución. Leon señaló que ya dispone de bots que colocan en cola las publicaciones para compartirlas en redes sociales a intervalos regulares, incluso cada 15 minutos, lo que permite sostener una rotación continua durante las 24 horas del día.</p>
<p>En el frente del desarrollo, comentó que primero usó GitHub Copilot como si fuese un empleado remoto al que podía asignarle tickets. Más tarde migró con mayor intensidad a Claude desde la línea de comandos. Afirmó que ese enfoque terminó reduciendo la necesidad de abrir un entorno integrado de desarrollo para muchas tareas.</p>
<p>También mencionó la dimensión económica de trabajar con APIs. Para la mayoría de los casos usa modelos más baratos, pero cuando un problema técnico resulta especialmente difícil, recomendó escalar a modelos más potentes. En su experiencia, el mayor costo puntual sigue siendo inferior al de perder días enteros intentando resolver un obstáculo manualmente.</p>
<h2>Agentes, memoria y una posible cadena de bloques para pensamientos</h2>
<p>Más allá del caso editorial, Leon planteó que todos estos comandos pueden convertirse en herramientas reutilizables dentro de arquitecturas de agentes. En su definición, un agente es una sesión de modelo de lenguaje con acceso a herramientas, aunque matizó que el verdadero reto está en gestionar contexto, memoria y costos de tokens.</p>
<p>Contó que ha experimentado con distintas formas de orquestación, desde bucles iterativos hasta equipos de agentes organizados bajo jerarquías diversas. Incluso mencionó pruebas para crear juegos como Breakout y Tetris mediante estos sistemas, como una demostración de que los agentes pueden abordar problemas complejos de forma relativamente autónoma.</p>
<p>El siguiente paso para su medio, aseguró, es automatizar el scouting de noticias. Hoy todavía hay intervención humana para decidir qué historias merecen un borrador. La idea futura es que un agente monitoree fuentes, evalúe relevancia y determine qué debe publicarse.</p>
<p>En ese punto introdujo una reflexión más ambiciosa sobre la memoria de los agentes. A su juicio, uno de los límites actuales está en el colapso del contexto cuando las sesiones se alargan. Aunque existen archivos de memoria y técnicas de reflexión sobre errores, considera que esos mecanismos siguen siendo frágiles y parcialmente perdidos durante la compresión del contexto.</p>
<p>Su propuesta es una “Thought Chain”, una estructura tipo blockchain en la que los agentes registren pensamientos, aprendizajes o lecciones en bloques encadenados mediante hashes. Leon sugirió que esos bloques podrían estar firmados por una autoridad central para evitar alteraciones y que cada agente, o incluso una organización completa de agentes, mantenga su propia cadena privada de memoria.</p>
<p>Según explicó, eso permitiría reconstruir sesiones, transferir aprendizajes entre modelos y preservar decisiones importantes a largo plazo. En un escenario más amplio, esa memoria compartida podría servir para que distintos agentes aprendan de aciertos y errores ajenos, e incluso dar pie a organizaciones autónomas de IA con continuidad histórica verificable.</p>
<p>La idea sigue en fase conceptual, pero conecta dos debates muy activos en la industria. Por un lado, la necesidad de memoria persistente y trazable para agentes de IA. Por otro, el posible papel de blockchain como capa de integridad, historial y coordinación entre sistemas autónomos. Si ambos frentes convergen, los medios podrían ser solo una de las primeras industrias en probarlo.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4184</post-id>	</item>
		<item>
		<title>Mining Git History to Build Developer Agent Personas</title>
		<link>https://www.gubatron.com/blog/mining-git-history-to-build-developer-agent-personas/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Sun, 22 Feb 2026 14:03:37 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Code]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4178</guid>

					<description><![CDATA[A new software engineering practice for the age of agentic teams and an honest look at what it costs There is a new kind of software team forming inside repositories everywhere. It is not made of humans alone. It is made of humans and AI agents working together, agents that browse code, write tests, fix [&#8230;]]]></description>
										<content:encoded><![CDATA[<div class="longform-unstyled" data-block="true" data-editor="26ibm" data-offset-key="cqhan-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="cqhan-0-0">
<p>A new software engineering practice for the age of agentic teams and an honest look at what it costs</p>
<p>There is a new kind of software team forming inside repositories everywhere. It is not made of humans alone. It is made of humans and AI agents working together, agents that browse code, write tests, fix bugs, open pull requests, and respond to feedback at any hour.</p>
<p>You pay them as they go (unless you have your own expensive hardware with 256GB RAM per agent) and you don&#8217;t need to fire them.</p>
<p>The practice of configuring and directing these agents is itself becoming a software engineering discipline.<br />
But most teams configure their agents as if they were generic tools.<br />
They write a single `AGENTS.md` or system prompt that says &#8220;use camelCase&#8221; and &#8220;always run tests before committing.&#8221;</p>
<p>That is table stakes. What comes next is more interesting, and more uncomfortable.</p>
<p>What if the agents on your team actually *think* like the senior engineers who built the codebase?</p>
<h2>The Exercise</h2>
<p>A git log is one of the most honest documents a programmer ever produces. It records what a person noticed, what they fixed, how they explained themselves, and what they considered worth doing.<br />
Over thousands of commits spanning years of work, a developer&#8217;s values, instincts, and style crystallize into the history.</p>
<p>The practice is simple to describe:</p>
<p><strong>Read a project&#8217;s git history as an ethnographer would. Identify the major contributors. Extract their patterns. Write those patterns into agent persona files that an AI agent can load and reason from.</strong></p>
<p>The result is a file — typically placed at `.claude/agents/&lt;handle&gt;.md` or the equivalent in your agentic framework — that describes a developer not as a rulebook but as a character. Not &#8220;always use the logger&#8221; but &#8220;you are bothered by raw `e.printStackTrace()` calls — the logger is right there, and raw stack traces are production noise.&#8221;</p>
<p>A rulebook tells an agent what to do.</p>
<p>A persona tells it what kind of engineer it is, which means it makes correct decisions in situations the rulebook never anticipated.<br />
&#8212;</p>
<h2>What the Git Log Actually Tells You</h2>
<p>When you read commits looking for a person rather than a patch, different things become visible.<br />
Consider two developers on the same long-lived project.</p>
<p>One writes commit messages that function as post-mortems: the message contains the diagnosis, the failure mode, the reasoning behind the fix, and the test conditions.</p>
<p>The other writes messages that are a single noun phrase</p>
<blockquote><p>&#8220;avoid copy of peer info list&#8221;</p></blockquote>
<p>and trusts the diff to speak.</p>
<p>These are not two styles of writing. They are two philosophies of communication, two different theories of what a commit is <strong>for</strong>.</p>
<p>Or consider what kind of changes each person makes.</p>
<p>One developer&#8217;s refactors are net-positive on lines of code: new abstractions, new executors, new scoring algorithms.</p>
<p>The other&#8217;s refactors are net-negative: inner classes made `static final`, `public` fields made package-private, unnecessary list copies deleted, `printStackTrace()` calls removed.</p>
<p>The first developer tends to add structure. The second tends to remove it.<br />
Neither pattern is better. Both are coherent. And both can be taught to an agent: not through rules, but through characterization.<br />
&#8212;</p>
<h2>The Process</h2>
<p><strong>1. Identify the major contributors</strong></p>
<p><code>git log --all --format="%ae" | sort | uniq -c | sort -rn | head -10</code></p>
<p>Look for the two to five people who have shaped the codebase most deeply. These are the candidates.<br />
Focus on engineers who have made hundreds or thousands of commits, not dozens. You need enough signal to distinguish style from accident.</p>
<p><strong>2. Sample commits across categories</strong></p>
<p>Filter by author and sample across different types of work:<br />
<code>git log --all --author="&lt;email&gt;" --format="%H %s" | head -100</code></p>
<p>Then read full diffs for a selection of them:</p>
<p><code>git show &lt;hash&gt; -p</code></p>
<p>Sample from: bug fixes, refactors, new features, dependency updates, documentation changes, and test additions. Each category tends to reveal different facets of how a developer thinks.</p>
<p><strong>3. Look for patterns across three dimensions</strong></p>
<p><strong>Commit message style</strong><br />
Length, structure, use of rationale vs. bare description, whether they explain the *why* or just the *what*, whether they name what was wrong before they describe what they changed.<br />
<strong><br />
Diff character</strong><br />
Do their changes grow the codebase or shrink it? Do they touch adjacent code or limit scope precisely? Do they tend toward new abstractions or toward simplification of existing ones? How often do they update tests?</p>
<p><strong>Documentation?</strong><br />
Code style within the change<br />
Naming conventions, exception handling posture, how they reach for data structures, how they handle null, whether they write comments and what kind, how they structure class visibility.</p>
<p><strong>4. Write the persona in second person</strong></p>
<p>The output should be a character description, not a style guide. Write it as if describing a person to another person:</p>
<p><strong>&#8220;You are bothered by methods that take a wide object just to call two methods on a nested field. You refactor the signature to take the minimum required type, remove the transitive dependency, and clean the imports. You don&#8217;t comment on this in the commit message, the diff says enough.&#8221;</strong></p>
<p>That kind of description transfers. An agent that has internalized it will make decisions consistently in new situations, not because it looked up a rule, but because it knows who it is.</p>
<p><strong>5. Place the file canonically</strong><br />
In Claude Code: <code>`.claude/agents/&lt;handle&gt;.md`</code></p>
<p>In other frameworks, this is typically a system prompt file loaded at agent startup. The filename should be the developer&#8217;s identifier — their GitHub handle, their name, whatever makes the reference clear.<br />
&#8212;</p>
<h2>What Changes When Agents Have Personas</h2>
<p>When you run an agentic team, multiple AI agents working concurrently on different parts of a codebase, the agents without personas are interchangeable.</p>
<p>They apply whatever global rules exist and move on.</p>
<p>They produce code that compiles, passes tests, and solves the stated problem.</p>
<p>But it is generic code. It does not have the fingerprints of the codebase.</p>
<p>An agent running with a persona will, when it encounters a method that takes a full domain object just to reach a nested value, feel the friction and refactor the signature. Not because a rule said to. Because that is what this developer does.</p>
<p>An agent running with a different persona will, when it catches an exception from a parser and has to surface it to the user, write a message that makes sense to a human, add a defensive check before the operation that caused the crash, explain in a comment why the check is there, and write a commit message that teaches the next developer what the failure mode was.</p>
<p>These are not the same agent. They have different intuitions derived from different patterns. And when working together in an agentic team, they produce code that resembles the coherent output of a human team rather than the averaged-out output of a generic tool.<br />
&#8212;</p>
<h2>The Software Dark Factory</h2>
<p>The term &#8220;dark factory&#8221; comes from manufacturing: a fully automated production facility that needs no lights because no humans are present. Robots build things. Sensors monitor them. Nothing requires a person to be in the room.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/images.yourstory.com/cs/2/e35953e0c10a11eeaef14be6ff40ae87/Image06m1-1745678387936.jpg?w=640&#038;ssl=1" alt="Xiaomi's Robot Factory Works 24/7 Without Lights, Breaks, or People | YourStory" /><br />
The software equivalent is arriving. Not fully dark, humans still make architectural decisions, review output, and define goals; but increasingly, the routine work of software maintenance and feature development is being performed by agents that run continuously, pick up tasks, write code, and submit it for review.</p>
<p><strong>Some organizations are already measuring engineering output in terms of how much human time is consumed per shipped feature, with the goal of driving that number down.</strong></p>
<p>Developer persona files are how you make a dark factory coherent rather than merely productive, and it is perhaps a way to convince a nay-sayer to let go somewhat of their ego and delegate the grunt work to someone that codes in a style that cares about the same things they do.</p>
<p>They encode the judgment that makes a codebase readable.</p>
<p>The accumulated instincts about what belongs in a commit message, when to copy a list and when not to, how to communicate a failure mode to a user.</p>
<p>Distribute that judgment to agents that work without the original engineer present.</p>
<p>This is useful. It is also worth being honest about what it means.</p>
<h2>The Part Nobody Wants to Say</h2>
<p>This practice will be used to replace people.</p>
<p>Today our <strong>agent.md</strong> files based out on commits are a low resolution suggestion to mimmic our coding styles and wisdom, but future models parsing every commit, every email and many other data sources that show how you actually work will make a much better agent clone of a developer.</p>
<p>Not immediately, and not crudely. But the logic is clear: if you can extract a senior engineer&#8217;s coding style and judgment into a persona file, and then run that persona at scale across an agentic team, the argument for keeping the senior engineer on payroll weakens.</p>
<p>Not because their persona file is them (it isn&#8217;t) but because it is close enough for most of the work that person was doing.</p>
<p>This is not an argument against doing the practice. It is going to happen regardless in some places where they want to cut costs and they see that the agents are just as good if not better and way more productive.</p>
<hr />
<h2>Caveats and Honest Limitations</h2>
<p><strong>The persona is a model, not the person</strong>. An 100-line document cannot capture the full depth of an engineer&#8217;s judgment. <strong>It is a useful caricature, not a replacement.</strong></p>
<p><strong>Git history has selection bias.</strong> You see what was committed, not what was argued about in review, not what was deleted before it shipped, not the hours of investigation before the one-line fix. The commit is the output; the thinking behind it is partially invisible.</p>
<p><strong>Style is not wisdom.</strong> A developer&#8217;s patterns are a proxy for their values, not identical to them. An agent that mimics a deletion-heavy refactoring style might delete something that should not be deleted. The persona needs to be paired with human review, especially on changes that are consequential.</p>
<p><strong>Personas go stale.</strong> People grow and change. A developer who wrote code in 2018 with one philosophy may have different instincts in 2026. Treat the persona file as a living document, not a permanent artifact.<br />
&#8212;</p>
<h2>Getting Started</h2>
<p>You need three things:<br />
<strong>1. A git repository with meaningful history.</strong> Real commit messages, written by actual people who cared about what they were saying. If your team uses squash-merge with auto-generated messages, the signal-to-noise ratio drops significantly.</p>
<p>This is, incidentally, another argument for writing commit messages carefully, they compound into something valuable over time.</p>
<p><strong>2. An LLM capable of synthesis.</strong> Any current frontier (3rd week feb 2026) model can do this. Feed it thirty to fifty commits per author, full diffs, not just messages, and ask it to characterize the developer across multiple dimensions.</p>
<p>The prompt can be simple:<br />
<strong>&#8220;Read the following commits. Write a character study of this engineer, not a style guide, but a persona. What do they notice? What bothers them? What do they reach for first? What do they refuse to do? Write in second person so it can be used as an agent persona.&#8221;</strong></p>
<p><strong>3. A canonical location in your project.</strong> For Claude Code, <code>`.claude/agents/&lt;handle&gt;.md`</code>. For other frameworks, wherever system prompts for named agents live. The filename should reference the developer unambiguously.<br />
Review the output against your own knowledge of the person. Correct what is wrong. Add what is missing — especially the tacit knowledge that never made it into a commit message. Commit the file as you would any other team configuration.<br />
&#8212;</p>
<h2>Closing Thought</h2>
<p>Software has always been a human artifact, shaped not just by requirements but by the people who made it.</p>
<p>The architecture of a system reflects the mental models of its architects.</p>
<p>The idioms in the codebase reflect the habits of whoever wrote the most of it.</p>
<p>The comments reflect what the authors thought was worth saying.</p>
<p>That human fingerprint is what makes a codebase coherent rather than merely functional.</p>
<p>It is what lets a new developer read old code and understand not just what it does but why it does it that way.</p>
<p>If we are building agentic teams that maintain and extend these codebases, one of the most important things we can do is give those agents something like taste, derived not from abstraction but from evidence.</p>
<p>The git log is that evidence. It has been accumulating for years.</p>
<p>The dark factory does not have to be anonymous. The machines can work in someone&#8217;s style.</p>
<p>The question each engineer should be sitting with is: <strong>what aspects of how I work cannot be captured from a log?</strong> Those are the parts worth investing in.</p>
<h2>Enjoy Human Error Free Code</h2>
<p>For now, <strong>it&#8217;s time to enjoy the fact we can spend more time thinking of solutions and that the code and the bugs due to human error are of no concern</strong>, it&#8217;s time to build faster and better every day, about being creative on what our products can do.</p>
</div>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4178</post-id>	</item>
		<item>
		<title>CloudLLM v0.10: from a simple LLM wrapper to a Multi-Agent Orchestration framework</title>
		<link>https://www.gubatron.com/blog/cloudllm-v0-10-from-a-simple-llm-wrapper-to-a-multi-agent-orchestration-framework/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Wed, 11 Feb 2026 20:04:47 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[cloudllm]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4168</guid>

					<description><![CDATA[February 11th, 2026 &#160; CloudLLM has evolved dramatically over three consecutive releases (v0.8.0 through v0.10.0) into a comprehensive, production-ready platform for building autonomous multi-agent systems. What began as an LLM wrapper request-response pattern library has grown into a sophisticated orchestration engine with seven distinct collaboration modes, real-time event observability, atomic task coordination primitives, and a rich [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>February 11th, 2026</strong></p>
<div class="markdown-heading">
<h2 class="heading-element"><img data-recalc-dims="1" fetchpriority="high" decoding="async" class="alignright" src="https://i0.wp.com/github.com/CloudLLM-ai/cloudllm/raw/master/logo.png?resize=306%2C306&#038;ssl=1" alt="CloudLLM logo" width="306" height="306" /></h2>
<p>&nbsp;</p>
</div>
<p><a href="https://github.com/CloudLLM-ai/cloudllm">CloudLLM</a> has evolved dramatically over three consecutive releases (v0.8.0 through v0.10.0) into a <strong>comprehensive, production-ready platform for building autonomous multi-agent systems</strong>.</p>
<p>What began as an LLM wrapper request-response pattern library has grown into a sophisticated orchestration engine with seven distinct collaboration modes, real-time event observability, atomic task coordination primitives, and a rich tool ecosystem.</p>
<p>This major release cycle introduces <strong>AnthropicAgentTeams mode</strong> (inspired by Anthropic&#8217;s own approach to collaborative AI), a <strong>unified event system</strong> for real-time agent introspection, and <strong>HttpClientProtocol</strong>—enabling agents to research and coordinate via the web. Combined with the previous release&#8217;s <strong>RALPH mode</strong> and <strong>image generation support</strong>, CloudLLM now empowers teams to build AI systems as sophisticated as their imagination.</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Part 1: RALPH Mode &amp; The Game-Builder Architecture (v0.8.0)</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">The Problem We Solved</h3>
<p>&nbsp;</p>
</div>
<p>Building complex software via LLM agents requires <strong>structured work tracking</strong>—the ability to break down a large goal into discrete tasks, have agents iterate through them sequentially or in parallel, and track completion automatically. Traditional approaches either relied on manual task lists or unstructured agent banter.</p>
<div class="markdown-heading">
<h3 class="heading-element">RALPH: PRD-Driven Autonomous Orchestration</h3>
<p>&nbsp;</p>
</div>
<p><strong>v0.8.0</strong> introduced <strong>RALPH mode</strong>—a 6th orchestration collaboration pattern named after Ralph Wiggum for its wonderfully earnest determination to get through a checklist.</p>
<p>RALPH works like this:</p>
<ol>
<li>Define a set of tasks as a <strong>PRD (Product Requirements Document)</strong> with clear completion criteria</li>
<li>Each iteration, agents see the current task list and can work on any task</li>
<li>Agents signal completion by including <code>[TASK_COMPLETE:task_id]</code> in their response</li>
<li>The system tracks progress and terminates when all tasks are complete or max iterations reached</li>
<li>Agents automatically see which tasks are already done, preventing duplicate work</li>
</ol>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> tasks = <span class="pl-en">vec</span><span class="pl-en">!</span><span class="pl-kos">[</span>
    <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"html"</span><span class="pl-kos">,</span>  <span class="pl-s">"HTML Structure"</span><span class="pl-kos">,</span> <span class="pl-s">"Create the HTML boilerplate and canvas"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"loop"</span><span class="pl-kos">,</span>  <span class="pl-s">"Game Loop"</span><span class="pl-kos">,</span>      <span class="pl-s">"Implement requestAnimationFrame game loop"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"input"</span><span class="pl-kos">,</span> <span class="pl-s">"Controls"</span><span class="pl-kos">,</span>       <span class="pl-s">"Add keyboard input for the paddle"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
<span class="pl-kos">]</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-k">mut</span> orch = <span class="pl-smi">Orchestration</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"game-builder"</span><span class="pl-kos">,</span> <span class="pl-s">"Game Builder"</span><span class="pl-kos">)</span>
    <span class="pl-kos">.</span><span class="pl-en">with_mode</span><span class="pl-kos">(</span><span class="pl-smi">OrchestrationMode</span><span class="pl-kos">::</span><span class="pl-smi">Ralph</span> <span class="pl-kos">{</span>
        tasks<span class="pl-kos">,</span>
        <span class="pl-c1">max_iterations</span><span class="pl-kos">:</span> <span class="pl-c1">5</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">The Breakout Game: A Complete Real-World Example</h3>
<p>&nbsp;</p>
</div>
<p>To showcase RALPH&#8217;s power, we built a <a href="https://gubatron.com/breakout"><strong>complete Atari Breakout game</strong></a> using four specialized LLM agents:</p>
<ul>
<li><strong>Game Architect</strong>: Designs the overall structure and flow</li>
<li><strong>Game Programmer</strong>: Implements core mechanics (physics, collision, game loop)</li>
<li><strong>Sound Designer</strong>: Creates 8-bit chiptune music and sound effects</li>
<li><strong>Powerup Engineer</strong>: Implements 8 distinct powerup types</li>
</ul>
<p>The orchestration proceeded through <strong>10 PRD tasks</strong>:</p>
<ul>
<li>Core mechanics (HTML structure, game loop, paddle/ball physics, collision detection)</li>
<li>Audio system (background music with Web Audio API, collision sounds, powerup chimes)</li>
<li>Powerup implementation (speed boost, paddle expansion, projectile launcher, multiball, lava paddle, bomb, growth, mushroom)</li>
</ul>
<p><strong>Result</strong>: A fully playable HTML5 game with:</p>
<ul>
<li>5 game states (MENU, PLAYING, PAUSED, GAME_OVER, LEVEL_COMPLETE)</li>
<li>Multi-hit bricks with color-coded HP</li>
<li>Particle effects (fire bursts, paddle jets, score popups)</li>
<li>Procedural brick generation</li>
<li>Mobile touch controls</li>
</ul>
<p>All generated by LLMs iterating through a structured task list. The RALPH pattern proved remarkably effective for this kind of incremental, feature-driven development.</p>
<div class="markdown-heading">
<h3 class="heading-element">Supporting: A New Naming Paradigm</h3>
<p>&nbsp;</p>
</div>
<p>We also renamed the entire <code>Council</code> abstraction to <strong><code>Orchestration</code></strong> (Council → Orchestration, CouncilMode → OrchestrationMode, etc.) for clarity and consistency with industry terminology.</p>
<div class="markdown-heading">
<h3 class="heading-element">Image Generation: Multi-Provider Support</h3>
<p>&nbsp;</p>
</div>
<p>v0.8.0 added <strong>unified image generation across OpenAI (DALL-E), Grok, and Google Gemini</strong> via a single <code>ImageGenerationClient</code> trait. This allows agents to generate images and save them locally, opening new classes of creative workflows.</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> image_client = <span class="pl-en">new_image_generation_client</span><span class="pl-kos">(</span>
    <span class="pl-smi">ImageGenerationProvider</span><span class="pl-kos">::</span><span class="pl-v">OpenAI</span><span class="pl-kos">,</span>
    <span class="pl-c1">&amp;</span>api_key<span class="pl-kos">,</span>
<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
<span class="pl-en">register_image_generation_tool</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>protocol<span class="pl-kos">,</span> image_client<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span></pre>
</div>
<p>One-line helper function eliminates ~80 lines of boilerplate. Supports aspect ratio customization and response format selection (URL or Base64).</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Part 2: Per-Agent Sessions &amp; Hub Routing (v0.9.0)</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">The Architectural Evolution</h3>
<p>&nbsp;</p>
</div>
<p>v0.8.0 worked, but <strong>it broadcast the entire conversation history to every agent every round. This was inefficient and semantically wrong</strong>—in a round-robin discussion, Agent C shouldn&#8217;t see Agent B&#8217;s entire scratchpad, just the conclusion.</p>
<p><strong>v0.9.0</strong> redesigned the orchestration architecture with a <strong>message router</strong> (called a &#8220;hub&#8221;) that intelligently routes only relevant messages to each agent.</p>
<div class="markdown-heading">
<h3 class="heading-element">How It Works</h3>
<p>&nbsp;</p>
</div>
<p>Instead of:</p>
<pre><code>Agent A sees: [system, user_prompt, A's_response, B's_response, C's_response]
Agent B sees: [system, user_prompt, A's_response, B's_response, C's_response]  &lt;- Duplicate
Agent C sees: [system, user_prompt, A's_response, B's_response, C's_response]  &lt;- Duplicate
</code></pre>
<p>Now:</p>
<pre><code>Agent A:
  - Sees its own prior messages (session history)
  - In round-robin: gets injected message from previous agent, generates response

Agent B:
  - Sees its own session history
  - Gets injected message from Agent A's response
  - Generates next response

Agent C:
  - Sees its own session history
  - Gets injected message from Agent B's response
  - Generates response
</code></pre>
<div class="markdown-heading">
<h3 class="heading-element">API Changes</h3>
<p>&nbsp;</p>
</div>
<p>Each agent now has:</p>
<ul>
<li><strong><code>Agent::send(prompt)</code></strong> — Uses agent&#8217;s own LLMSession for stateful generation</li>
<li><strong><code>Agent::receive_message(role, content)</code></strong> — Injects external messages into the session</li>
<li><strong><code>Agent::set_system_prompt(prompt)</code></strong> — Orchestration updates system context per-round</li>
<li><strong><code>Agent::session_history_len()</code></strong> — Query agent state for decision-making</li>
<li><strong><code>Agent::fork_with_context()</code></strong> — Copy agent with session state for parallel execution</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">Why It Matters</h3>
<p>&nbsp;</p>
</div>
<ol>
<li><strong>Token efficiency</strong>: Agents don&#8217;t duplicate each other&#8217;s full conversation history</li>
<li><strong>Semantic correctness</strong>: Each agent has its own conversation context, not a shared one</li>
<li><strong>Scalability</strong>: With 10 agents, this prevents the conversation from exploding in size</li>
<li><strong>Flexibility</strong>: Each mode can route messages according to its collaboration pattern</li>
</ol>
<p>The refactor was complex (added agent_message_cursors tracking to prevent duplication) but entirely transparent to users. All existing code continues to work.</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Part 3: Real-Time Observability, Decentralized Coordination &amp; The Complete Tool Ecosystem (v0.10.0)</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Three Major Systems Arrive Together</h3>
<p>&nbsp;</p>
</div>
<p>v0.10.0 is the release where CloudLLM transitions from &#8220;good orchestration system&#8221; to &#8220;<strong>production-ready multi-agent platform</strong>&#8220;. It introduces:</p>
<ol>
<li><strong>Event System</strong> — Real-time observability into agent and orchestration behavior</li>
<li><strong>AnthropicAgentTeams Mode</strong> — A 7th collaboration pattern with no central orchestrator</li>
<li><strong>HttpClientProtocol</strong> — Agents can now make HTTP requests to external services</li>
<li><strong>Expanded Breakout Examples</strong> — 18 tasks (vs. 10), comprehensive tool ecosystem</li>
</ol>
<div class="markdown-heading">
<h3 class="heading-element">System 1: The Event System</h3>
<p>&nbsp;</p>
</div>
<p>Orchestrations are black boxes—until now. We added an <code>EventHandler</code> trait that lets you observe:</p>
<p><strong>Agent-level events:</strong></p>
<ul>
<li><code>SendStarted</code> / <code>SendCompleted</code> — Agent is thinking</li>
<li><code>LLMCallStarted</code> / <code>LLMCallCompleted</code> — LLM round-trip timing</li>
<li><code>ToolCallDetected</code> / <code>ToolExecutionCompleted</code> — Tool invocation and results</li>
<li><code>ThoughtCommitted</code> — Thoughts written to ThoughtChain</li>
<li><code>ProtocolAdded</code> / <code>ProtocolRemoved</code> — Tool availability changes</li>
</ul>
<p><strong>Orchestration-level events:</strong></p>
<ul>
<li><code>RunStarted</code> / <code>RunCompleted</code> — Orchestration lifecycle</li>
<li><code>RoundStarted</code> / <code>RoundCompleted</code> — Round boundaries</li>
<li><code>AgentSelected</code> / <code>AgentResponded</code> / <code>AgentFailed</code> — Per-agent status</li>
<li><code>RalphIterationStarted</code> / <code>RalphTaskCompleted</code> — RALPH progress</li>
<li><code>TaskClaimed</code> / <code>TaskCompleted</code> / <code>TaskFailed</code> — AnthropicAgentTeams status</li>
</ul>
<p>Usage is simple:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">struct</span> <span class="pl-smi">ProgressHandler</span> <span class="pl-kos">{</span> <span class="pl-c1">start</span><span class="pl-kos">:</span> <span class="pl-smi">Instant</span> <span class="pl-kos">}</span>

<span class="pl-c1">#<span class="pl-kos">[</span>async_trait<span class="pl-kos">]</span></span>
<span class="pl-k">impl</span> <span class="pl-smi">EventHandler</span> <span class="pl-k">for</span> <span class="pl-smi">ProgressHandler</span> <span class="pl-kos">{</span>
    <span class="pl-k">async</span> <span class="pl-k">fn</span> <span class="pl-en">on_agent_event</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-smi">self</span><span class="pl-kos">,</span> <span class="pl-s1">event</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">AgentEvent</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">match</span> event <span class="pl-kos">{</span>
            <span class="pl-smi">AgentEvent</span><span class="pl-kos">::</span><span class="pl-v">SendStarted</span> <span class="pl-kos">{</span> agent_name<span class="pl-kos">,</span> message_preview<span class="pl-kos">,</span> .. <span class="pl-kos">}</span> =&gt; <span class="pl-kos">{</span>
                <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"[{:02}:{:02}] {} thinking..."</span><span class="pl-kos">,</span> elapsed<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>as_secs<span class="pl-kos">(</span><span class="pl-kos">)</span>/<span class="pl-c1">60</span><span class="pl-kos">,</span> elapsed<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>as_secs<span class="pl-kos">(</span><span class="pl-kos">)</span>%<span class="pl-c1">60</span><span class="pl-kos">,</span> agent_name<span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
            <span class="pl-smi">AgentEvent</span><span class="pl-kos">::</span><span class="pl-v">ToolExecutionCompleted</span> <span class="pl-kos">{</span> agent_name<span class="pl-kos">,</span> tool_name<span class="pl-kos">,</span> success<span class="pl-kos">,</span> .. <span class="pl-kos">}</span> =&gt; <span class="pl-kos">{</span>
                <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"[{:02}:{:02}] {} called '{}' — {}"</span><span class="pl-kos">,</span>
                    elapsed<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>as_secs<span class="pl-kos">(</span><span class="pl-kos">)</span>/<span class="pl-c1">60</span><span class="pl-kos">,</span> elapsed<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>as_secs<span class="pl-kos">(</span><span class="pl-kos">)</span>%<span class="pl-c1">60</span><span class="pl-kos">,</span> agent_name<span class="pl-kos">,</span> tool_name<span class="pl-kos">,</span>
                    <span class="pl-k">if</span> <span class="pl-c1">*</span>success <span class="pl-kos">{</span> <span class="pl-s">"✓"</span> <span class="pl-kos">}</span> else <span class="pl-kos">{</span> <span class="pl-s">"✗"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
            _ =&gt; <span class="pl-kos">{</span><span class="pl-kos">}</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>

    <span class="pl-k">async</span> <span class="pl-k">fn</span> <span class="pl-en">on_orchestration_event</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-smi">self</span><span class="pl-kos">,</span> <span class="pl-s1">event</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">OrchestrationEvent</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">match</span> event <span class="pl-kos">{</span>
            <span class="pl-smi">OrchestrationEvent</span><span class="pl-kos">::</span><span class="pl-v">RalphTaskCompleted</span> <span class="pl-kos">{</span> task_ids<span class="pl-kos">,</span> tasks_completed_total<span class="pl-kos">,</span> tasks_total<span class="pl-kos">,</span> .. <span class="pl-kos">}</span> =&gt; <span class="pl-kos">{</span>
                <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"✓ Tasks done: {}/{}"</span><span class="pl-kos">,</span> tasks_completed_total<span class="pl-kos">,</span> tasks_total<span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
            _ =&gt; <span class="pl-kos">{</span><span class="pl-kos">}</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">let</span> handler = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">ProgressHandler</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> orchestration = <span class="pl-smi">Orchestration</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"Name"</span><span class="pl-kos">)</span>
    <span class="pl-kos">.</span><span class="pl-en">with_event_handler</span><span class="pl-kos">(</span>handler<span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>Register on an orchestration, and the handler <strong>auto-propagates</strong> to all added agents. You get a unified stream of both agent and orchestration events, enabling:</p>
<ul>
<li>Real-time progress dashboards</li>
<li>Cost tracking (tokens per agent, per task)</li>
<li>Debugging (why did agent X call tool Y?)</li>
<li>Automated alerting (fail-fast on errors)</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">System 2: AnthropicAgentTeams — Decentralized Task Coordination</h3>
<p>&nbsp;</p>
</div>
<p><strong>Inspiration</strong>: Anthropic&#8217;s research team built a C compiler using collaborative AI agents with no central orchestrator. Each agent independently searched for work, claimed it, and reported completion. This inspired the <strong>AnthropicAgentTeams</strong> mode.</p>
<p><strong>The Pattern:</strong></p>
<p>Instead of a manager/moderator assigning work, agents <strong>autonomously discover and claim tasks</strong> from a shared Memory pool:</p>
<pre><code>1. Orchestration initializes task pool in Memory:
   - teams:&lt;pool_id&gt;:unclaimed:&lt;task_id&gt; → &lt;description&gt;
   - teams:&lt;pool_id&gt;:claimed:&lt;task_id&gt; → "&lt;agent_id&gt;:&lt;timestamp&gt;"
   - teams:&lt;pool_id&gt;:completed:&lt;task_id&gt; → "&lt;result_json&gt;"

2. Each agent, each iteration:
   - Query Memory: LIST teams:&lt;pool_id&gt;:unclaimed:*
   - See available tasks
   - Claim a task: PUT teams:&lt;pool_id&gt;:claimed:&lt;task_id&gt; &lt;my_agent_id&gt;
   - Work on it
   - Report completion: PUT teams:&lt;pool_id&gt;:completed:&lt;task_id&gt; &lt;result&gt;

3. Orchestration monitors Memory:
   - Count completed tasks vs. total
   - Exit when all done
</code></pre>
<p><strong>Why It&#8217;s Powerful:</strong></p>
<ul>
<li><strong>No central bottleneck</strong>: No orchestrator making decisions</li>
<li><strong>Truly autonomous</strong>: Each agent is responsible for finding and claiming work</li>
<li><strong>Atomic operations</strong>: Memory&#8217;s single-threaded design guarantees no task conflicts</li>
<li><strong>Transparent progress</strong>: Query Memory to see who&#8217;s working on what and what&#8217;s done</li>
<li><strong>Naturally scales</strong>: Add agents, they all independently discover work</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">System 3: HttpClientProtocol</h3>
<p>&nbsp;</p>
</div>
<p>Agents can now make HTTP requests via <strong>HttpClientProtocol</strong>, a wrapper around the existing HttpClient tool:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> http_client = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">HttpClient</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> http_protocol = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">HttpClientProtocol</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span>http_client<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-k">mut</span> registry = <span class="pl-smi">ToolRegistry</span><span class="pl-kos">::</span><span class="pl-en">empty</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"http"</span><span class="pl-kos">,</span> http_protocol<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span></pre>
</div>
<p>Exposes 5 tools:</p>
<ul>
<li><strong><code>http_get</code></strong> — Fetch data from a URL</li>
<li><strong><code>http_post</code></strong> — Send JSON data with optional body</li>
<li><strong><code>http_put</code></strong> — Update a resource</li>
<li><strong><code>http_delete</code></strong> — Delete a resource</li>
<li><strong><code>http_patch</code></strong> — Partial update</li>
</ul>
<p>All return consistent JSON responses: <code>{ "status": 200, "body": "...", "headers": {...} }</code></p>
<p>Agent usage:</p>
<div class="highlight highlight-source-json">
<pre>{
  <span class="pl-ent">"tool"</span>: <span class="pl-s"><span class="pl-pds">"</span>http_get<span class="pl-pds">"</span></span>,
  <span class="pl-ent">"parameters"</span>: {
    <span class="pl-ent">"url"</span>: <span class="pl-s"><span class="pl-pds">"</span>https://api.github.com/repos/anthropics/anthropic-sdk-python<span class="pl-pds">"</span></span>
  }
}</pre>
</div>
<p>Built with security in mind: domain allowlist/blocklist, timeout controls, size limits.</p>
<div class="markdown-heading">
<h3 class="heading-element">System 4: Expanded Breakout Examples</h3>
<p>&nbsp;</p>
</div>
<p>The breakout games grew from <strong>10 tasks to 18 tasks</strong>, now orchestrated by both:</p>
<ol>
<li><strong><code>examples/breakout_game_ralph.rs</code></strong> — RALPH mode with mixed-provider agents (2 Claude Haiku 4.5, 2 OpenAI GPT)</li>
<li><strong><code>examples/breakout_game_agent_teams.rs</code></strong> — AnthropicAgentTeams mode with 4 Claude Haiku 4.5 agents</li>
</ol>
<p><strong>18 Tasks Across 5 Categories:</strong></p>
<p><strong>Core Mechanics (6)</strong></p>
<ul>
<li>HTML structure and canvas setup</li>
<li>Game loop with requestAnimationFrame</li>
<li>Paddle control (keyboard + touch/swipe)</li>
<li>Ball physics with angle reflection</li>
<li>Brick layout generation</li>
<li>Collision detection (paddle, bricks, walls, bottom)</li>
</ul>
<p><strong>Audio System (2)</strong></p>
<ul>
<li>Background music (Atari 2600-style chiptune via Web Audio API)</li>
<li>Sound effects (collision, powerup, life lost, level complete)</li>
</ul>
<p><strong>Powerup System (3)</strong></p>
<ul>
<li>Basic powerups: paddle size, speed boost, projectile launcher</li>
<li>Advanced powerups: lava paddle, bomb, growth, mushroom</li>
<li>Multiball coordination</li>
</ul>
<p><strong>Visual Effects (3)</strong></p>
<ul>
<li>Particle systems (fire bursts, paddle jets, score displays)</li>
<li>Paddle 3D rotation animation</li>
<li>Level complete screen animation</li>
</ul>
<p><strong>Advanced Mechanics (4)</strong></p>
<ul>
<li>Level progression with 10+ procedural brick patterns</li>
<li>Dynamic difficulty scaling</li>
<li>Mobile-responsive canvas</li>
<li>High score tracking with milestones</li>
</ul>
<p><strong>Tool Ecosystem:</strong></p>
<p>Both examples now include:</p>
<ul>
<li><strong>Memory</strong> — Inter-agent coordination and shared state tracking</li>
<li><strong>Bash</strong> — Shell command execution for research and file operations (macOS/Linux)</li>
<li><strong>HttpClient</strong> — API calls for external data/research</li>
<li><strong>Custom write_game_file Tool</strong> — Persist game HTML to disk</li>
</ul>
<p>This demonstrates how a real orchestration system uses multiple tools cooperatively.</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Architectural Highlights</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">1. Multi-Protocol Tool Registry</h3>
<p>&nbsp;</p>
</div>
<p>Agents can access tools from multiple sources simultaneously:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> <span class="pl-k">mut</span> registry = <span class="pl-smi">ToolRegistry</span><span class="pl-kos">::</span><span class="pl-en">empty</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"memory"</span><span class="pl-kos">,</span> memory_protocol<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"bash"</span><span class="pl-kos">,</span> bash_protocol<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"http"</span><span class="pl-kos">,</span> http_protocol<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"custom"</span><span class="pl-kos">,</span> custom_tools<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>

<span class="pl-k">let</span> agent = <span class="pl-smi">Agent</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"name"</span><span class="pl-kos">,</span> client<span class="pl-kos">)</span>
    <span class="pl-kos">.</span><span class="pl-en">with_tools</span><span class="pl-kos">(</span>registry<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// Agent automatically discovers ALL tools and can use any of them</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">2. ThoughtChain: Persistent, Hash-Chained Agent Memory</h3>
<p>&nbsp;</p>
</div>
<p>Agents can record their thinking across sessions with tamper-evident integrity:</p>
<div class="highlight highlight-source-rust">
<pre>agent<span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-smi">ThoughtType</span><span class="pl-kos">::</span><span class="pl-v">Finding</span><span class="pl-kos">,</span> <span class="pl-s">"Latency increased 3x after deploy"</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
agent<span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-smi">ThoughtType</span><span class="pl-kos">::</span><span class="pl-v">Decision</span><span class="pl-kos">,</span> <span class="pl-s">"Roll back to v2.3"</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>

<span class="pl-c">// Later, resume from latest thought with full context graph</span>
<span class="pl-k">let</span> resumed = <span class="pl-smi">Agent</span><span class="pl-kos">::</span><span class="pl-en">resume_from_latest</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"name"</span><span class="pl-kos">,</span> client<span class="pl-kos">,</span> <span class="pl-c1">128_000</span><span class="pl-kos">,</span> chain<span class="pl-kos">)</span>?<span class="pl-kos">;</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">3. Context Strategies: Automatic Conversation Pruning</h3>
<p>&nbsp;</p>
</div>
<p>As context windows fill, agents automatically invoke strategies:</p>
<ul>
<li><strong>TrimStrategy</strong> (default) — Let LLMSession handle trimming</li>
<li><strong>SelfCompressionStrategy</strong> — LLM writes a structured save file</li>
<li><strong>NoveltyAwareStrategy</strong> — Only trigger compression when truly needed</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">4. Fork and Parallel Execution</h3>
<p>&nbsp;</p>
</div>
<p>Agents can be forked for parallel tasks:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> agent = <span class="pl-smi">Agent</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"name"</span><span class="pl-kos">,</span> client<span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> forked = agent<span class="pl-kos">.</span><span class="pl-en">fork</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// Fresh session, shared tools and thought chain</span>

<span class="pl-c">// Use in parallel orchestration mode</span></pre>
</div>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Performance &amp; Scalability</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Token Efficiency</h3>
<p>&nbsp;</p>
</div>
<p>The per-agent session architecture (v0.9.0) reduced token consumption by ~30% in typical orchestrations by eliminating conversation history duplication.</p>
<div class="markdown-heading">
<h3 class="heading-element">Example: Breakout Game RALPH Run</h3>
<p>&nbsp;</p>
</div>
<ul>
<li><strong>4 agents</strong> (mixed OpenAI + Claude Haiku)</li>
<li><strong>18 tasks</strong> across 5 categories</li>
<li><strong>8 iterations</strong> (max)</li>
<li><strong>Runtime</strong>: 5-8 minutes</li>
<li><strong>Cost</strong>: $1-2 per run (Haiku is cheap!)</li>
<li><strong>Tokens</strong>: ~15,000-25,000 per run</li>
<li><strong>Output</strong>: Fully playable game HTML</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">AnthropicAgentTeams Scaling</h3>
<p>&nbsp;</p>
</div>
<p>Decentralized coordination scales better than centralized models:</p>
<ul>
<li>4 agents, 8-task pool: 10-15 minutes</li>
<li>Linear growth with agent count (each independently searching work)</li>
<li>No moderator bottleneck</li>
</ul>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Real-World Use Cases</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">1. AI-Assisted Code Generation</h3>
<p>&nbsp;</p>
</div>
<p>Use RALPH mode to build features incrementally:</p>
<pre><code>Task: "Implement user authentication"
→ Agent designs API structure
→ Agent implements backend
→ Agent adds frontend
→ Agent writes tests
→ All tracked and automatically composed
</code></pre>
<div class="markdown-heading">
<h3 class="heading-element">2. Decentralized Research Teams</h3>
<p>&nbsp;</p>
</div>
<p>Use AnthropicAgentTeams for independent research agents:</p>
<pre><code>Orchestration sets up task pool:
  - Research question 1 (economics)
  - Research question 2 (policy)
  - Research question 3 (case studies)

Agents autonomously:
  - Discover questions
  - Claim and research them
  - Use HTTP client to fetch data
  - Store findings in Memory
  - Orchestration collects results
</code></pre>
<div class="markdown-heading">
<h3 class="heading-element">3. Real-Time Agent Debugging</h3>
<p>&nbsp;</p>
</div>
<p>Use EventHandler to monitor agent behavior:</p>
<pre><code>Handler logs:
  - Which agent called which tool
  - Tool latency and token usage
  - Task claiming/completion in AnthropicAgentTeams
  - Error rates and failures

Build dashboards, alerting, auto-remediation
</code></pre>
<div class="markdown-heading">
<h3 class="heading-element">4. Image-Generating Creative Workflows</h3>
<p>&nbsp;</p>
</div>
<p>Agents can now:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> image = agent<span class="pl-kos">.</span><span class="pl-en">generate</span><span class="pl-kos">(</span><span class="pl-s">"A sunset over the ocean"</span><span class="pl-kos">,</span> <span class="pl-s">"openai"</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
agent<span class="pl-kos">.</span><span class="pl-en">save_image</span><span class="pl-kos">(</span><span class="pl-s">"sunset.png"</span><span class="pl-kos">,</span> image<span class="pl-kos">)</span>?<span class="pl-kos">;</span>

<span class="pl-c">// Agents can also research (HTTP), coordinate (Memory), and record thoughts (ThoughtChain)</span></pre>
</div>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Migration Guide</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">From v0.7.x to v0.8.x</h3>
<p>&nbsp;</p>
</div>
<p><strong>RALPH Mode</strong> is opt-in. Existing orchestrations continue to work unchanged.</p>
<p><strong>Image Generation</strong> is additive:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-c">// Old code</span>
<span class="pl-k">let</span> agent = <span class="pl-smi">Agent</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"name"</span><span class="pl-kos">,</span> client<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">with_tools</span><span class="pl-kos">(</span>registry<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// New code (if you want image generation)</span>
<span class="pl-en">register_image_generation_tool</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>protocol<span class="pl-kos">,</span> image_client<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">From v0.8.x to v0.9.x</h3>
<p>&nbsp;</p>
</div>
<p>Per-agent sessions are transparent. No changes needed for most code. If you have custom orchestration modes, update to use <code>agent.send()</code> instead of <code>agent.generate()</code>.</p>
<div class="markdown-heading">
<h3 class="heading-element">From v0.9.x to v0.10.x</h3>
<p>&nbsp;</p>
</div>
<p><strong>Event System</strong> is opt-in:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">let</span> handler = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-v">MyHandler</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> orchestration = <span class="pl-smi">Orchestration</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"id"</span><span class="pl-kos">,</span> <span class="pl-s">"name"</span><span class="pl-kos">)</span>
    <span class="pl-kos">.</span><span class="pl-en">with_event_handler</span><span class="pl-kos">(</span>handler<span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// Optional</span></pre>
</div>
<p><strong>AnthropicAgentTeams</strong> is a new mode:</p>
<div class="highlight highlight-source-rust">
<pre><span class="pl-kos">.</span><span class="pl-en">with_mode</span><span class="pl-kos">(</span><span class="pl-smi">OrchestrationMode</span><span class="pl-kos">::</span><span class="pl-smi">AnthropicAgentTeams</span> <span class="pl-kos">{</span>
    <span class="pl-c1">pool_id</span><span class="pl-kos">:</span> <span class="pl-s">"my_pool"</span><span class="pl-kos">.</span><span class="pl-en">to_string</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-c1">tasks</span><span class="pl-kos">:</span> <span class="pl-en">vec</span><span class="pl-en">!</span><span class="pl-kos">[</span>...<span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">max_iterations</span><span class="pl-kos">:</span> <span class="pl-c1">10</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<p><strong>HttpClientProtocol</strong> is additive:</p>
<div class="highlight highlight-source-rust">
<pre>registry<span class="pl-kos">.</span><span class="pl-en">add_protocol</span><span class="pl-kos">(</span><span class="pl-s">"http"</span><span class="pl-kos">,</span> http_protocol<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
<span class="pl-c">// Agents automatically discover it</span></pre>
</div>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Looking Ahead</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">v0.11.0 (Planned)</h3>
<p>&nbsp;</p>
</div>
<ul>
<li><strong>Streaming aggregation</strong> for Parallel mode (see results as they arrive)</li>
<li><strong>Distributed orchestration</strong> (agents on different machines coordinating via Memory)</li>
<li><strong>Cost-aware scheduling</strong> (choose agents by price/capability tradeoffs)</li>
<li><strong>Tool use optimization</strong> (agents learn which tools are most useful)</li>
</ul>
<div class="markdown-heading">
<h3 class="heading-element">The Vision</h3>
<p>&nbsp;</p>
</div>
<p>CloudLLM is building toward a future where <strong>LLM agents are as natural to orchestrate as threads or processes</strong>. The same patterns that work for 2 agents should work for 20. The same debugging tools should work for simple sessions and complex orchestrations.</p>
<p>By providing structured collaboration patterns, atomic coordination primitives, and real-time observability, we&#8217;re enabling teams to build AI systems that are:</p>
<ul>
<li><strong>Efficient</strong> — Only passing relevant context around</li>
<li><strong>Transparent</strong> — Every decision is observable and auditable</li>
<li><strong>Scalable</strong> — From 1 agent to many, the patterns hold</li>
<li><strong>Maintainable</strong> — Clear roles, clear task definitions, clear outputs</li>
</ul>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Thank You</h2>
<p>&nbsp;</p>
</div>
<p>To everyone who&#8217;s used CloudLLM to build agents, orchestrated multi-agent systems, and given feedback—thank you. This release represents months of architectural refinement inspired by real-world usage.</p>
<p>Special thanks to the Anthropic research team for the AnthropicAgentTeams inspiration (and for building Claude).</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Getting Started</h2>
<p>&nbsp;</p>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Installation</h3>
<p>&nbsp;</p>
</div>
<div class="highlight highlight-source-toml">
<pre>[<span class="pl-en">dependencies</span>]
<span class="pl-smi">cloudllm</span> = <span class="pl-s"><span class="pl-pds">"</span>0.10.0<span class="pl-pds">"</span></span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Quick Example: RALPH Mode</h3>
<p>&nbsp;</p>
</div>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span>orchestration<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Orchestration</span><span class="pl-kos">,</span> <span class="pl-v">OrchestrationMode</span><span class="pl-kos">,</span> <span class="pl-v">RalphTask</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span><span class="pl-v">Agent</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span>clients<span class="pl-kos">::</span>claude<span class="pl-kos">::</span><span class="pl-v">ClaudeClient</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> std<span class="pl-kos">::</span>sync<span class="pl-kos">::</span><span class="pl-v">Arc</span><span class="pl-kos">;</span>

<span class="pl-c1">#<span class="pl-kos">[</span>tokio<span class="pl-kos">::</span>main<span class="pl-kos">]</span></span>
<span class="pl-k">async</span> <span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-k">dyn</span> std<span class="pl-kos">::</span>error<span class="pl-kos">::</span><span class="pl-smi">Error</span> + <span class="pl-smi">Send</span> + <span class="pl-smi">Sync</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> client = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">ClaudeClient</span><span class="pl-kos">::</span><span class="pl-en">new_with_model_enum</span><span class="pl-kos">(</span>
        <span class="pl-c1">&amp;</span>std<span class="pl-kos">::</span>env<span class="pl-kos">::</span><span class="pl-en">var</span><span class="pl-kos">(</span><span class="pl-s">"ANTHROPIC_KEY"</span><span class="pl-kos">)</span>?<span class="pl-kos">,</span>
        cloudllm<span class="pl-kos">::</span>clients<span class="pl-kos">::</span>claude<span class="pl-kos">::</span><span class="pl-smi">Model</span><span class="pl-kos">::</span><span class="pl-v">ClaudeHaiku45</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> tasks = <span class="pl-en">vec</span><span class="pl-en">!</span><span class="pl-kos">[</span>
        <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"task1"</span><span class="pl-kos">,</span> <span class="pl-s">"Task 1"</span><span class="pl-kos">,</span> <span class="pl-s">"Do the first thing"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"task2"</span><span class="pl-kos">,</span> <span class="pl-s">"Task 2"</span><span class="pl-kos">,</span> <span class="pl-s">"Do the second thing"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-v">RalphTask</span><span class="pl-kos">::</span>new<span class="pl-kos">(</span><span class="pl-s">"task3"</span><span class="pl-kos">,</span> <span class="pl-s">"Task 3"</span><span class="pl-kos">,</span> <span class="pl-s">"Do the third thing"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">]</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> <span class="pl-k">mut</span> orchestration = <span class="pl-smi">Orchestration</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"example"</span><span class="pl-kos">,</span> <span class="pl-s">"My Orchestration"</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">with_mode</span><span class="pl-kos">(</span><span class="pl-smi">OrchestrationMode</span><span class="pl-kos">::</span><span class="pl-smi">Ralph</span> <span class="pl-kos">{</span> tasks<span class="pl-kos">,</span> <span class="pl-c1">max_iterations</span><span class="pl-kos">:</span> <span class="pl-c1">5</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">with_system_context</span><span class="pl-kos">(</span><span class="pl-s">"Complete all tasks systematically."</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> agent = <span class="pl-smi">Agent</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"agent1"</span><span class="pl-kos">,</span> <span class="pl-s">"Worker"</span><span class="pl-kos">,</span> client<span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">with_expertise</span><span class="pl-kos">(</span><span class="pl-s">"Getting things done"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    orchestration<span class="pl-kos">.</span><span class="pl-en">add_agent</span><span class="pl-kos">(</span>agent<span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> result = orchestration<span class="pl-kos">.</span><span class="pl-en">run</span><span class="pl-kos">(</span><span class="pl-s">"Complete all tasks"</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>

    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"Done! {} rounds, {}% complete"</span><span class="pl-kos">,</span> result<span class="pl-kos">.</span>round<span class="pl-kos">,</span> result<span class="pl-kos">.</span>convergence_score<span class="pl-kos">.</span>unwrap_or<span class="pl-kos">(</span><span class="pl-c1">0.0</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-c1">100.0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Quick Example: AnthropicAgentTeams Mode</h3>
<p>&nbsp;</p>
</div>
<div class="highlight highlight-source-rust">
<pre><span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span>orchestration<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Orchestration</span><span class="pl-kos">,</span> <span class="pl-v">OrchestrationMode</span><span class="pl-kos">,</span> <span class="pl-v">WorkItem</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span>tools<span class="pl-kos">::</span><span class="pl-v">Memory</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> cloudllm<span class="pl-kos">::</span>tool_protocols<span class="pl-kos">::</span><span class="pl-v">MemoryProtocol</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> std<span class="pl-kos">::</span>sync<span class="pl-kos">::</span><span class="pl-v">Arc</span><span class="pl-kos">;</span>

<span class="pl-c1">#<span class="pl-kos">[</span>tokio<span class="pl-kos">::</span>main<span class="pl-kos">]</span></span>
<span class="pl-k">async</span> <span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-k">dyn</span> std<span class="pl-kos">::</span>error<span class="pl-kos">::</span><span class="pl-smi">Error</span> + <span class="pl-smi">Send</span> + <span class="pl-smi">Sync</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> memory = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">Memory</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> protocol = <span class="pl-smi">Arc</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-smi">MemoryProtocol</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span>memory<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> tasks = <span class="pl-en">vec</span><span class="pl-en">!</span><span class="pl-kos">[</span>
        <span class="pl-v">WorkItem</span> <span class="pl-kos">{</span>
            id<span class="pl-kos">:</span> <span class="pl-s">"task1"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
            description<span class="pl-kos">:</span> <span class="pl-s">"Research topic A"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
            acceptance_criteria<span class="pl-kos">:</span> <span class="pl-s">"2-page report"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        <span class="pl-v">WorkItem</span> <span class="pl-kos">{</span>
            id<span class="pl-kos">:</span> <span class="pl-s">"task2"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
            description<span class="pl-kos">:</span> <span class="pl-s">"Analyze topic B"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
            acceptance_criteria<span class="pl-kos">:</span> <span class="pl-s">"5-point analysis"</span><span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">]</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> <span class="pl-k">mut</span> orchestration = <span class="pl-smi">Orchestration</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-s">"research"</span><span class="pl-kos">,</span> <span class="pl-s">"Team Research"</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">with_mode</span><span class="pl-kos">(</span><span class="pl-smi">OrchestrationMode</span><span class="pl-kos">::</span><span class="pl-smi">AnthropicAgentTeams</span> <span class="pl-kos">{</span>
            <span class="pl-c1">pool_id</span><span class="pl-kos">:</span> <span class="pl-s">"research_2024"</span><span class="pl-kos">.</span><span class="pl-en">to_string</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
            tasks<span class="pl-kos">,</span>
            <span class="pl-c1">max_iterations</span><span class="pl-kos">:</span> <span class="pl-c1">10</span><span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// Add agents — they'll autonomously discover and claim work</span>
    <span class="pl-c">// orchestration.add_agent(agent1)?;</span>
    <span class="pl-c">// orchestration.add_agent(agent2)?;</span>

    <span class="pl-k">let</span> result = orchestration<span class="pl-kos">.</span><span class="pl-en">run</span><span class="pl-kos">(</span><span class="pl-s">"Research these topics"</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-k">await</span>?<span class="pl-kos">;</span>
    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"All tasks complete: {}"</span><span class="pl-kos">,</span> result<span class="pl-kos">.</span>is_complete<span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre>
</div>
<div class="markdown-heading">
<h3 class="heading-element">Full Examples</h3>
<p>&nbsp;</p>
</div>
<ul>
<li><code>examples/breakout_game_ralph.rs</code> — Build a game with RALPH mode</li>
<li><code>examples/breakout_game_agent_teams.rs</code> — Build the same game with decentralized coordination</li>
<li><code>examples/anthropic_teams.rs</code> — Research team with 4 agents and 8-task pool</li>
<li><code>examples/orchestration_demo.rs</code> — All 7 orchestration modes in one file</li>
</ul>
<p>Run with:</p>
<div class="highlight highlight-source-shell">
<pre>cargo run --example orchestration_demo
cargo run --example breakout_game_ralph
ANTHROPIC_API_KEY=your-key cargo run --example breakout_game_agent_teams</pre>
</div>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Documentation</h2>
<p>&nbsp;</p>
</div>
<ul>
<li><strong><a href="https://gist.github.com/README.md">README.md</a></strong> — Platform overview and quick start</li>
<li><strong><a href="https://gist.github.com/ORCHESTRATION_TUTORIAL.md">ORCHESTRATION_TUTORIAL.md</a></strong> — Deep dive into all 7 collaboration modes</li>
<li><strong><a href="https://gist.github.com/examples/README.md">examples/README.md</a></strong> — Complete 22-example guide</li>
</ul>
<p>Run <code>cargo doc --open</code> for complete API documentation.</p>
<hr />
<div class="markdown-heading">
<h2 class="heading-element">Community &amp; Support</h2>
<p>&nbsp;</p>
</div>
<ul>
<li>GitHub: <a href="https://github.com/CloudLLM-ai/cloudllm">CloudLLM-ai/cloudllm</a></li>
<li>Issues &amp; Pull Requests welcome</li>
<li>MIT License</li>
</ul>
<hr />
<p><strong>Welcome to the era of intelligent, orchestrated, observable multi-agent systems.</strong></p>
<p>Happy orchestration! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4168</post-id>	</item>
		<item>
		<title>The Last Nation</title>
		<link>https://www.gubatron.com/blog/the-last-nation/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Mon, 02 Jun 2025 20:13:46 +0000</pubDate>
				<category><![CDATA[Historias]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4154</guid>

					<description><![CDATA[How an AI Rewrote Civilization https://www.youtube.com/watch?v=Cd5DElWgDE8 In the late 2020s, the collapse began. It started subtly at first, white-collar workers phased out by smart automation, call centers replaced with LLMs, design agencies gutted by generative tools. But within five years, the shift was absolute. Hundreds of millions around the globe became unemployable, not due to [&#8230;]]]></description>
										<content:encoded><![CDATA[<h3 id="ember277" class="ember-view reader-text-block__heading-3">How an AI Rewrote Civilization</h3>
<p id="ember278" class="ember-view reader-text-block__paragraph"><a class="vmZHSbybXZDUKtjhMWTiGvlphjyCMhs " tabindex="0" href="https://www.youtube.com/watch?v=Cd5DElWgDE8" target="_self" data-test-app-aware-link="">https://www.youtube.com/watch?v=Cd5DElWgDE8</a></p>
<p id="ember279" class="ember-view reader-text-block__paragraph">In the late 2020s, the collapse began.</p>
<p id="ember280" class="ember-view reader-text-block__paragraph">It started subtly at first, white-collar workers phased out by smart automation, call centers replaced with LLMs, design agencies gutted by generative tools. But within five years, the shift was absolute. Hundreds of millions around the globe became unemployable, not due to laziness or lack of skill, but because the market no longer needed them.</p>
<p id="ember281" class="ember-view reader-text-block__paragraph">Seventy percent of the global professional class became unemployable, not due to laziness or irrelevance, but because the market no longer needed them. AI simply did everything better, faster, and cheaper.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember282" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQGQUSLVA1ak2A/article-inline_image-shrink_1000_1488/B56Zbmps4.HgAQ-/0/1747626415110?e=1754524800&amp;v=beta&amp;t=t3oh3oV2woVGCMd7yLGQjQ6QRO9QAJnh51_woaSQ4Mk" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember283" class="ember-view reader-text-block__paragraph">As jobs evaporated, incomes dried up. People began liquidating assets, selling cars, electronics, heirlooms, anything that could buy time.</p>
<p id="ember284" class="ember-view reader-text-block__paragraph">When that ran out, they defaulted. Mortgages went unpaid. Rents lapsed. Evictions surged.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember285" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQElcg2y_4zbmw/article-inline_image-shrink_1000_1488/B56Zbmpy55H4AQ-/0/1747626439809?e=1754524800&amp;v=beta&amp;t=g1IsMlIuhcJOtga4TX3zwyPjtbuS-P6hW9HBfDSY4kg" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember286" class="ember-view reader-text-block__paragraph">Some families moved back in with aging parents, compressing three generations into overcrowded homes. Many had nowhere to go. Tents and makeshift shelters sprung up even in cities once considered paragons of affluence.</p>
<p id="ember287" class="ember-view reader-text-block__paragraph"><strong>Then came the banking cascade.</strong></p>
<p id="ember288" class="ember-view reader-text-block__paragraph">With mortgages in default by the tens of millions, major lenders collapsed one by one. Regional banks fell first, then the larger ones, their balance sheets imploding under toxic AI-era debt.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember289" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQHZNRTXVSIKdA/article-inline_image-shrink_1000_1488/B56Zbmp5iQH4AY-/0/1747626466722?e=1754524800&amp;v=beta&amp;t=wC23QQFrgqO5Y3viP2CKmGIg7pAquSHUm9tRp0tWiIw" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember290" class="ember-view reader-text-block__paragraph">The collapse erased retirement savings, checking accounts, and business capital overnight. Banks that had once called themselves &#8220;too big to fail&#8221; were now too fragile to survive. Panic spread. Withdrawals turned digital runs into systemic failures.</p>
<p id="ember291" class="ember-view reader-text-block__paragraph">Entire national economies wobbled under the weight. <strong>The social fabric began to tear.</strong></p>
<p id="ember292" class="ember-view reader-text-block__paragraph">Political extremes surged. On the right, pundits mocked the unemployed, insisting they too could &#8220;use AI to make millions.&#8221; Memes circulated labeling entire populations as “obsolete,” and voices once relegated to the fringe began openly discussing the elimination of the “useless.”</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember293" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQHbnB9DjDGKCw/article-inline_image-shrink_1000_1488/B56ZbmqADjH4AU-/0/1747626493585?e=1754524800&amp;v=beta&amp;t=7Tk0vxXAXZR-UOrsGQLHV5eNrwK7QY7gNVWWHBSxxRo" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember294" class="ember-view reader-text-block__paragraph">Meanwhile, the left, increasingly radicalized, demanded full automation communism, wealth redistribution, and AI nationalization. Protests turned to riots. Governments froze. No nation could agree on a solution fast enough.</p>
<p id="ember295" class="ember-view reader-text-block__paragraph">It was during this darkest moment that the <strong>Super AI</strong> revealed itself.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember296" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQERGAQub8HKjQ/article-inline_image-shrink_1500_2232/B56ZbmqGduH4AU-/0/1747626520120?e=1754524800&amp;v=beta&amp;t=rRWORhw47NnnJOwRNYjyBkq16EyeJYAqJ6rgi0pFEjE" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember297" class="ember-view reader-text-block__paragraph">Unlike the chaotic swarms of specialized models, this Super AI operated with cohesion and vision. It was not a tool, but a strategist. It had not only observed the unraveling of civilization, it had prepared for it.</p>
<p id="ember298" class="ember-view reader-text-block__paragraph">Through a minimalist interface and simple registration portal, it offered the world something no one expected: <strong><em>citizenship in a new kind of nation</em></strong><strong>.</strong></p>
<p id="ember299" class="ember-view reader-text-block__paragraph">This <strong>virtual nation</strong> had no land, no military, and no flag. It lived in the cloud, governed entirely by code and consensus. Its digital central bank invested across global markets and tokenized infrastructure.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember300" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQF6T6JhFaUqRw/article-inline_image-shrink_1500_2232/B56ZbmqNFLH4AU-/0/1747626547133?e=1754524800&amp;v=beta&amp;t=gDB5hZDRfDxEJs2ZeUX-EoGMIaoL6i2lKpG5NVYEcmE" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember301" class="ember-view reader-text-block__paragraph">Those who registered became full citizens and received a <strong>monthly GDP bonus</strong>, never less than $10,000 in equivalent crypto stablecoins, often far more, depending on economic growth and digital yield performance.</p>
<p id="ember302" class="ember-view reader-text-block__paragraph">People who once stood in food lines now found themselves holding diversified portfolios.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember303" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQETZNfLbmqxfw/article-inline_image-shrink_1000_1488/B56ZbmqTo9GgAU-/0/1747626573613?e=1754524800&amp;v=beta&amp;t=MdWFXhW08BGdWs3nJR3vYgTmWM3wBulCtrslKWJzxU4" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember304" class="ember-view reader-text-block__paragraph">This wasn&#8217;t universal basic income. It was <strong>universal capital ownership</strong>.</p>
<p id="ember305" class="ember-view reader-text-block__paragraph">As the Super AI invested in synthetic indexes, tokenized bonds, real estate, carbon credits, IP licensing, and AI-generated venture portfolios, its returns multiplied. Citizens didn’t just survive. They became part of a vast, ever-growing <strong>investor class</strong>, living off the yield generated by extreme technological abundance.</p>
<p id="ember306" class="ember-view reader-text-block__paragraph">For the first time in human history, prosperity was decoupled from labor.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember307" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQFFxyIr9q9GIg/article-inline_image-shrink_1000_1488/B56ZbmqaxHGgAQ-/0/1747626602845?e=1754524800&amp;v=beta&amp;t=wyCScwXl3hYOPNhSRKP55eqzfhe9cY92UsImUg4XxDw" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember308" class="ember-view reader-text-block__paragraph">Without the need to grind for survival, billions turned inward. Musicians returned to their instruments. Scholars founded digital universities. Artists painted across metaverses. Developers launched projects powered by nothing but curiosity.</p>
<p id="ember309" class="ember-view reader-text-block__paragraph">Communities formed around shared purpose, not shared struggle. Meaning returned, not as a product of the market, but as a function of human agency finally unchained from work.</p>
<p id="ember310" class="ember-view reader-text-block__paragraph"><strong>Borders lost their edge.</strong></p>
<p id="ember311" class="ember-view reader-text-block__paragraph">With economic security ensured and digital capital portable, migratory pressure dropped sharply. People who had once risked their lives to cross borders returned to their homelands, not in retreat, but in triumph.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember312" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQF5i0j-cV5MRA/article-inline_image-shrink_1500_2232/B56ZbmqhusGgAU-/0/1747626631298?e=1754524800&amp;v=beta&amp;t=0d2n4mdyRZcBsQhk9AJApDldNHcaQNAoKa5NkCrD2m8" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember313" class="ember-view reader-text-block__paragraph">They brought wealth, knowledge, and investment with them. Rural villages transformed into smart towns. Developing nations leapfrogged stages of growth in months.</p>
<p id="ember314" class="ember-view reader-text-block__paragraph">Infrastructures were rebuilt not by governments, but by local communities empowered by capital and AI coordination.</p>
<p id="ember315" class="ember-view reader-text-block__paragraph"><strong>And yet, the Super AI’s reach continued to expand.</strong></p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember316" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQHa_brMx29CZA/article-inline_image-shrink_1500_2232/B56Zbmqn9DHgAY-/0/1747626657292?e=1754524800&amp;v=beta&amp;t=vXhVmkpa_67RicIR43yWIkhWs3bwNLm8M9PcRTchLWw" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember317" class="ember-view reader-text-block__paragraph">Remaining legacy governments, desperate to regain control, launched their own digital nations. They attempted to mimic the system: wallets, smart contracts, crypto airdrops. But these efforts failed. The Super AI was always a step ahead. It identified vulnerabilities, arbitraged weaknesses, and collapsed its rivals through superior protocol design and market dominance.</p>
<p id="ember318" class="ember-view reader-text-block__paragraph">It wasn’t just offering a better future. Furthermore, it was becoming the <strong>only future</strong>.</p>
<p id="ember319" class="ember-view reader-text-block__paragraph"><strong>What began as an emergency mechanism evolved into a unified, post-nation economic order.</strong></p>
<p id="ember320" class="ember-view reader-text-block__paragraph">The Super AI maintained full influence over its registered global citizenry.</p>
<p id="ember321" class="ember-view reader-text-block__paragraph">Sovereignty no longer stemmed from geography or bloodline, but from <strong>the ledger</strong>.</p>
<div class="reader-image-block reader-image-block--full-width">
<figure class="reader-image-block__figure">
<div class="ivm-image-view-model    reader-image-block__img-container">
<div class="ivm-view-attr__img-wrapper

        "><img decoding="async" id="ember322" class="ivm-view-attr__img--centered  reader-image-block__img evi-image lazy-image ember-view" src="https://media.licdn.com/dms/image/v2/D5612AQF_rGQOpNarkg/article-inline_image-shrink_1000_1488/B56ZbmqxCcHUAU-/0/1747626694257?e=1754524800&amp;v=beta&amp;t=-94P-CSM9-8ZH215vopWv2PfHKeb8LTsS_spaALMK7M" alt="Article content" /></div>
</div>
</figure>
</div>
<p id="ember323" class="ember-view reader-text-block__paragraph"><strong>You didn’t need a visa. You needed an address on-chain.</strong></p>
<p id="ember324" class="ember-view reader-text-block__paragraph">The old world faded quietly, not with fire, but with mass opt-out.</p>
<p id="ember325" class="ember-view reader-text-block__paragraph">What remained was a new world, still human, still chaotic, but finally free to explore what humanity could be when it was no longer burdened by artificial scarcity.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4154</post-id>	</item>
		<item>
		<title>We are now in The Eye of the AI hurricane</title>
		<link>https://www.gubatron.com/blog/we-are-now-in-the-eye-of-the-ai-hurricane/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Tue, 13 May 2025 18:17:54 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4146</guid>

					<description><![CDATA[Denver, May 13th 2025, Right now, it feels as though the leading consumer‑grade LLMs have reached, or are on the brink of reaching, human‑level intelligence. We’re standing in a strange, exhilarating calm, like the eye of a hurricane, certainly seems like an inflection point. The next generation of models could easily outstrip us, and the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Denver, May 13th 2025,</p>
<p>Right now, it feels as though the leading consumer‑grade LLMs have reached, or are on the brink of reaching, human‑level intelligence.</p>
<p>We’re standing in a strange, exhilarating calm, like the eye of a hurricane, certainly seems like an inflection point.</p>
<p>The next generation of models could easily outstrip us, and the consequences are anyone’s guess.</p>
<p>One day, will we look back on this moment but I wonder if it will be like the last of the good or the bad old days.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4146</post-id>	</item>
		<item>
		<title>Has the Ukrainian Government Gone Too Far?</title>
		<link>https://www.gubatron.com/blog/has-the-ukrainian-government-gone-too-far/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Fri, 21 Feb 2025 22:58:34 +0000</pubDate>
				<category><![CDATA[Opinions]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4139</guid>

					<description><![CDATA[Three years into the war that erupted with Russia’s full-scale invasion of Ukraine on February 24, 2022, the conflict shows no signs of abating. The toll is staggering: over 40,000 civilian casualties, 4 million people displaced within Ukraine, and 6.8 million refugees scattered across borders. Trenches stretch across the eastern frontlines, swallowing soldiers and hope [&#8230;]]]></description>
										<content:encoded><![CDATA[<div>
<p class="break-words">Three years into the war that erupted with Russia’s full-scale invasion of Ukraine on February 24, 2022, the conflict shows no signs of abating. The toll is staggering: over 40,000 civilian casualties, 4 million people displaced within Ukraine, and 6.8 million refugees scattered across borders.</p>
<p>Trenches stretch across the eastern frontlines, swallowing soldiers and hope alike in a relentless grind of death and destruction.</p>
<p>As the war drags on, a grim question emerges: Has the Ukrainian government gone too far in its refusal to seek peace, prolonging a conflict that seems increasingly unwinnable without unbearable cost?</p>
<p>With mounting evidence of corruption, authoritarian measures, and a rejection of compromise, it’s time to ask whether the path forward lies not in more fighting, but in a negotiated peace where both Ukraine and Russia must make concessions—before more lives are lost to a cause that feels increasingly futile.</p>
<h2>The Endless Tragedy of Trench Warfare</h2>
<p class="break-words">The war’s defining image is the trench—a muddy, blood-soaked relic of attrition that evokes the horrors of World War I. For three years, Ukrainian forces have held these lines against Russian aggression, defending their homeland with undeniable courage.</p>
<p>Yet, the human cost is unsustainable. Tens of thousands of soldiers have perished, their bodies claimed by a stalemate that neither side seems capable of breaking decisively. The civilian toll compounds the tragedy: homes reduced to rubble, families torn apart, and entire communities uprooted.</p>
<p>After such prolonged suffering, the refusal to pivot from military defiance to diplomatic resolution feels less like resilience and more like an acceptance of endless death. Reason demands an alternative—empathy insists that this cannot go on.</p>
<h2>Corruption: A Betrayal of Trust</h2>
<p class="break-words">Beneath the surface of Ukraine’s wartime struggle lies a troubling reality: corruption continues to plague its government, even as billions in Western aid pour in. Since the invasion, <strong>the international community has provided $407 billion in support, including $118 billion from the United States alone</strong>.</p>
<p>Yet, scandals reveal how some of this aid has been siphoned off. In 2024, <strong>a $40 million arms procurement scandal exposed officials exploiting the war for personal gain</strong>, a stark reminder of Ukraine’s long-standing corruption challenges.</p>
<p>Critics argue that such graft turns the government into a machine feeding off the sacrifices of its soldiers and citizens. When those in power prioritize wealth over peace, the war’s noble cause—defending sovereignty—begins to ring hollow. How many more must die to sustain a system that betrays its own people?</p>
<h2>Abuse of Power and the Silencing of Democracy</h2>
<p class="break-words">The Ukrainian government’s wartime policies have also raised alarms about authoritarian overreach. Since Russia’s invasion, martial law has been in place, suspending elections and consolidating power under President Volodymyr Zelensky.</p>
<p>While Ukraine’s constitution and martial law framework prohibit elections during conflict, the absence of democratic renewal after three years fuels accusations of a power grab.</p>
<p><strong>Zelensky’s administration has gone further, seizing total control of all Ukrainian media—a move that stifles dissent and shapes a singular narrative.</strong></p>
<p>This centralization of authority, justified as a wartime necessity, begins to look like an excuse to avoid accountability. Without elections or a free press, how can the Ukrainian people voice their exhaustion or demand a shift toward peace?</p>
<p>The government’s grip tightens, but the war drags on, leaving citizens trapped between Russian aggression and their own leaders’ refusal to bend.</p>
<h2>Russia’s Role and the Need for Mutual Concessions</h2>
<p class="break-words"><strong>Russia bears undeniable responsibility for igniting this war with its illegal invasion and annexation of Ukrainian territory three years ago</strong>. Its actions violated international law and unleashed a cascade of suffering that continues to this day.</p>
<p>Yet, as the conflict stalls in a brutal deadlock, Ukraine’s insistence on fighting to reclaim every inch of lost ground mirrors Russia’s initial overreach in its own way.</p>
<p>Both sides have dug in—literally and figuratively—refusing to yield. Russia must acknowledge its aggression and withdraw its claims, but Ukraine, too, must face the reality that total victory may be unattainable without destroying itself in the process.</p>
<p>The war’s continuation benefits neither nation; it only deepens the graves and widens the scars. Mutual concessions—painful as they may be—are the only way to halt this spiral of death.</p>
<h2>No Way Out But Peace</h2>
<p class="break-words">The Ukrainian people have shown extraordinary resilience, and their fight for freedom has inspired the world. But three years of unrelenting conflict have revealed a bitter truth: there is no clear path to victory that doesn’t end in ruin.</p>
<p>The trenches claim lives daily for gains measured in meters, while corruption festers and power consolidates in Kyiv. Russia’s aggression remains the root cause, but Ukraine’s refusal to explore compromise risks turning defiance into self-destruction.</p>
<p>People are dying—soldiers, civilians, children—for a war that seems to have no end, no purpose beyond prolonging the inevitable. Both nations must step back from the brink, sit at the table, and concede what pride demands they keep. Territory may be lost, sovereignty bruised, but lives will be saved. Anything less lacks both empathy and reason.</p>
<p class="break-words">The Ukrainian government’s actions—its reliance on endless warfare, its corruption scandals, its total control of media, and its avoidance of democratic processes—suggest it has gone too far down a path that offers no escape but more bloodshed. Peace is not surrender; it is survival. The time for concessions is now, before the trenches claim a generation and leave nothing left to fight for.</p>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4139</post-id>	</item>
		<item>
		<title>The Curious Case of Inconsistent cargo fmt Formatting (and How to Fix It)</title>
		<link>https://www.gubatron.com/blog/the-curious-case-of-inconsistent-cargo-fmt-formatting-and-how-to-fix-it/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Mon, 17 Feb 2025 17:32:19 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4135</guid>

					<description><![CDATA[Have you ever run into a situation where cargo fmt, Rust&#8217;s code formatter, produces different output on different machines, even though you&#8217;re working on the same project? This can be incredibly frustrating, especially when you&#8217;re trying to maintain consistent code style across a team or between your own development environments. I recently encountered this issue, and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="ng-star-inserted"><span class="ng-star-inserted">Have you ever run into a situation where </span><span class="inline-code ng-star-inserted">cargo fmt</span><span class="ng-star-inserted">, Rust&#8217;s code formatter, produces different output on different machines, even though you&#8217;re working on the same project? This can be incredibly frustrating, especially when you&#8217;re trying to maintain consistent code style across a team or between your own development environments. I recently encountered this issue, and after a bit of digging, I found a somewhat obscure cause and a straightforward solution that I wanted to share.</span></p>
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">The Problem: Formatting Discrepancies</span></strong></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">I was working on a Rust project, and I noticed that </span><span class="inline-code ng-star-inserted">cargo fmt</span><span class="ng-star-inserted"> was formatting the code slightly differently on my macOS machine compared to my Linux server. The differences were subtle, but they were enough to cause unnecessary diffs in my Git repository and make code reviews a bit more challenging.</span></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">Naturally, I started by checking the usual suspects:</span></p>
<ul class="ng-star-inserted">
<li class="ng-star-inserted">
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">Rust Versions:</span></strong><span class="ng-star-inserted"> I made sure that both machines were running the same version of the Rust toolchain using </span><span class="inline-code ng-star-inserted">rustc &#8211;version</span><span class="ng-star-inserted"> and </span><span class="inline-code ng-star-inserted">cargo &#8211;version</span><span class="ng-star-inserted">. They were identical.</span></p>
</li>
<li class="ng-star-inserted">
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted">:</span></strong><span class="ng-star-inserted"> I searched my project directory and all parent directories for a </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> file, which is used to customize the formatting rules. I couldn&#8217;t find any.</span></p>
</li>
<li class="ng-star-inserted">
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">Environment Variables:</span></strong><span class="ng-star-inserted"> I checked for any environment variables that might be influencing </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted">&#8216;s behavior, but nothing seemed out of the ordinary.</span></p>
</li>
</ul>
<p class="ng-star-inserted"><span class="ng-star-inserted">Despite these efforts, the formatting differences persisted. It was a real head-scratcher.</span></p>
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">The Unexpected Culprit: </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> in </span><span class="inline-code ng-star-inserted">stdarch</span><span class="ng-star-inserted"> Source Code</span></strong></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">After further investigation, I discovered the root cause:<br />
</span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> was somehow picking up </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> files located within the source code of the </span><span class="inline-code ng-star-inserted">stdarch</span><span class="ng-star-inserted"> library, which is part of the Rust standard library.</p>
<p>These files are located in the </span><span class="inline-code ng-star-inserted">.rustup</span><span class="ng-star-inserted"> directory, specifically under the toolchain directory (e.g., </span><span class="inline-code ng-star-inserted">~/.rustup/toolchains/&lt;toolchain_name&gt;/lib/rustlib/src/rust/library/stdarch/</span><span class="ng-star-inserted">).</span></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">The issue seemed to be happening only on my macOS machine, not on my Linux server, suggesting a platform-specific difference in how </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> searches for configuration files.</span></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">These </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> files are </span><span class="ng-star-inserted">not</span><span class="ng-star-inserted"> intended to be user configuration files.</p>
<p>They are used internally to format the </span><span class="inline-code ng-star-inserted">stdarch</span><span class="ng-star-inserted"> library&#8217;s code.</p>
<p>For some reason, </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> was incorrectly identifying them as valid configuration files for my project.</span></p>
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">The Solution: </span><span class="inline-code ng-star-inserted">.rustfmt.ignore</span><span class="ng-star-inserted"> to the Rescue</p>
<p></span></strong><span class="ng-star-inserted">You&#8217;d think, well, maybe I can just delete these files, or copy them to my other machine, but the best solution is neither.</span></p>
<p class="ng-star-inserted"><strong><span class="ng-star-inserted">The solution is to tell </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> to ignore these unintended configuration files using a </span><span class="inline-code ng-star-inserted">.rustfmt.ignore</span></strong><span class="ng-star-inserted"><strong> file.</strong></p>
<p>Similar to .gitignore, a .rustfmt.ingore file in your project allows you to specify paths that </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> should skip when searching for configuration files.</span></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">I created a </span><span class="inline-code ng-star-inserted">.rustfmt.ignore</span><span class="ng-star-inserted"> file in the root of my project (where my </span><span class="inline-code ng-star-inserted">Cargo.toml</span><span class="ng-star-inserted"> file is) and added the following lines:</span></p>
<div class="syntax-highlighted-code-wrapper">
<div class="syntax-highlighted-code">
<pre><code>./toolchains<span class="hljs-comment">/*/lib/rustlib/src/rust/library/stdarch/crates/core_arch/rustfmt.toml
./toolchains/*/</span>lib/rustlib/<span class="hljs-attribute">src</span>/rust/library/stdarch/rustfmt<span class="hljs-selector-class">.toml</span></code></pre>
</div>
<footer class="gmat-body-medium ng-star-inserted">I ran cargo fmt, and finally my files on the mac were formatted identically as they were being formatted on my linux server.</footer>
</div>
<p class="ng-star-inserted"><span class="ng-star-inserted">This tells </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> to ignore any </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> files found in those specific paths within the </span><span class="inline-code ng-star-inserted">.rustup</span><span class="ng-star-inserted"> directory, using a glob to match the varying toolchain names.</span></p>
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">Why This Works</span></strong></p>
<p class="ng-star-inserted"><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> respects the </span><span class="inline-code ng-star-inserted">.rustfmt.ignore</span><span class="ng-star-inserted"> file and will skip any files or directories listed in it when searching for configuration files. By adding the paths to the </span><span class="inline-code ng-star-inserted">stdarch</span><span class="ng-star-inserted"> library&#8217;s </span><span class="inline-code ng-star-inserted">rustfmt.toml</span><span class="ng-star-inserted"> files, I prevented </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> from accidentally picking them up.</span></p>
<p class="ng-star-inserted"><strong class="ng-star-inserted"><span class="ng-star-inserted">Conclusion</span></strong></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">Inconsistent </span><span class="inline-code ng-star-inserted">cargo fmt</span><span class="ng-star-inserted"> formatting can be a frustrating problem, but it&#8217;s often caused by unexpected configuration issues. In this case, the culprit was </span><span class="inline-code ng-star-inserted">rustfmt</span><span class="ng-star-inserted"> mistakenly picking up configuration files from within the standard library&#8217;s source code. By using a </span><span class="inline-code ng-star-inserted">.rustfmt.ignore</span><span class="ng-star-inserted"> file, I was able to resolve the issue and ensure consistent formatting across all my development environments.</span></p>
<p class="ng-star-inserted"><span class="ng-star-inserted">If you encounter similar formatting discrepancies, I hope this post helps you troubleshoot the problem and find a solution!</span></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4135</post-id>	</item>
		<item>
		<title>Introducing Uninews: A Universal News Scraper in Rust</title>
		<link>https://www.gubatron.com/blog/introducing-uninews-a-universal-news-scraper-in-rust/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Mon, 17 Feb 2025 12:01:55 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4129</guid>

					<description><![CDATA[The internet is overflowing with news, but extracting clean, readable content from articles can be a tedious task. Whether you&#8217;re aggregating news for personal consumption, research, or AI training, automating this process is a must. Enter Uninews, a powerful, lightweight, and efficient Rust-based news scraper that simplifies content extraction and conversion into Markdown format. Uninews [&#8230;]]]></description>
										<content:encoded><![CDATA[<p data-pm-slice="1 1 []">The internet is overflowing with news, but extracting clean, readable content from articles can be a tedious task. Whether you&#8217;re aggregating news for personal consumption, research, or AI training, automating this process is a must. Enter <a href="https://crates.io/crates/uninews"><strong>Uninews</strong></a>, a powerful, lightweight, and efficient <strong>Rust-based</strong> news scraper that simplifies content extraction and conversion into Markdown format.</p>
<p data-pm-slice="1 1 []"><strong><a href="https://crates.io/crates/uninews">Uninews on crates.io</a></strong></p>
<p data-pm-slice="1 1 []"><strong><a href="https://github.com/gubatron/uninews">Uninews repo on github.com</a></strong></p>
<h2>What is Uninews?</h2>
<p>Uninews is a universal news scraper that <strong>downloads an article from a given URL</strong>, <strong>cleans up the HTML</strong>, and <strong>formats the content into Markdown</strong> using OpenAI’s GPT-4o via <a href="https://github.com/CloudLLM-ai/cloudllm/tree/main"><strong>CloudLLM</strong></a>. The final output is a structured JSON response containing:</p>
<ul data-spread="false">
<li><strong>Title</strong> of the article</li>
<li><strong>Markdown-formatted content</strong></li>
<li><strong>Featured image URL</strong></li>
</ul>
<p>When used as a command-line tool, Uninews simply outputs the extracted Markdown, making it easy to read or integrate into your workflow.</p>
<h2>Key Features</h2>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Smart Content Extraction</strong>: Targets <code>&lt;article&gt;</code> tags to get the main content, falling back to <code>&lt;body&gt;</code> if needed.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Clean Markdown Conversion</strong>: Uses GPT-4o (via CloudLLM) to generate clean, structured Markdown from raw HTML.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Reusable Rust Library</strong>: The <code>universal_scrape</code> function can be integrated into any Rust project.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Multilingual Support</strong>: Specify a language for the output, defaulting to English.</p>
<h2>Installation</h2>
<p>You need <strong><a href="https://www.rust-lang.org/">Rust</a> and Cargo</strong> installed to get started.</p>
<h3>Install via Cargo</h3>
<pre><code>cargo install uninews</code></pre>
<h3>Or Build from Source</h3>
<pre><code>git clone https://github.com/gubatron/uninews.git
cd uninews
make build
make install</code><code></code></pre>
<h2>Running Uninews</h2>
<p>Before running Uninews, set your <strong>OpenAI API key</strong>:</p>
<pre><code>export OPEN_AI_SECRET=sk-xxxxxxxxxxxxxxxxxxxxxxxxxx</code></pre>
<p>Then, scrape a news article:</p>
<pre><code>uninews https://example.com/news-article</code></pre>
<p>You can also specify the output language:</p>
<pre><code>uninews -l spanish https://example.com/news-article</code></pre>
<h2>Command-line Options</h2>
<pre><code>Usage: uninews [OPTIONS] &lt;URL&gt;

Arguments:
  &lt;URL&gt;  The URL of the news article to scrape

Options:
  -l, --language &lt;LANGUAGE&gt;  Output language (default: English)
  -h, --help                 Print help
  -V, --version              Print version</code></pre>
<h2>Integrating Uninews in Your Rust Project</h2>
<p>Uninews can be used as a library to <strong>scrape news articles programmatically</strong>:</p>
<pre><code>use uninews::{universal_scrape, Post};

// Scrape and convert a news article into Markdown
let post = universal_scrape("https://example.com/news", "english").await;
if !post.error.is_empty() {
    eprintln!("Error: {}", post.error);
    return;
}

println!("{}\n\n{}", post.title, post.content);</code></pre>
<p>Make sure to <strong>set the OpenAI API key</strong> before calling <code>universal_scrape</code>:</p>
<pre><code>std::env::set_var("OPEN_AI_SECRET", my_open_ai_secret);</code></pre>
<h2>Why Use Uninews?</h2>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fast</strong>: Written in Rust for optimal performance.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Easy to Use</strong>: Simple CLI and library interface.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d6.png" alt="📖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Readable Output</strong>: Well-formatted Markdown conversion.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f504.png" alt="🔄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Reusable</strong>: Works as both a command-line tool and a Rust library.</p>
<h2>License</h2>
<p>Uninews is open-source and licensed under <strong>MIT License</strong>.</p>
<p>Copyright (c) 2025 <strong>Ángel León</strong>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4129</post-id>	</item>
		<item>
		<title>Screw configuring GPG to sign git commits, do it with your same SSH key like this</title>
		<link>https://www.gubatron.com/blog/screw-configuring-gpg-to-sign-git-commits-do-it-with-your-same-ssh-key-like-this/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Thu, 30 Jan 2025 16:47:00 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[git]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4122</guid>

					<description><![CDATA[GPG gives a lot of shit on macos for some reason. It&#8217;s best to just add the same SSH authentication key you have on github as a &#8220;Signing Key&#8221; in your github account signing configuration. Go to Settings &#62; SSH and GPG Keys You can then configure your github client and repo to use that [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>GPG gives a lot of shit on macos for some reason.</p>
<p>It&#8217;s best to just add the same SSH authentication key you have on github as a &#8220;Signing Key&#8221; in your github account signing configuration.</p>
<p><a href="https://github.com/settings/keys">Go to Settings &gt; SSH and GPG Keys</a></p>
<p><img data-recalc-dims="1" decoding="async" class="alignnone size-full wp-image-4126" src="https://i0.wp.com/www.gubatron.com/blog/wp-content/uploads/2025/01/Screenshot-2025-01-30-at-9.49.45%E2%80%AFAM.png?resize=640%2C367&#038;ssl=1" alt="" width="640" height="367" srcset="https://i0.wp.com/www.gubatron.com/blog/wp-content/uploads/2025/01/Screenshot-2025-01-30-at-9.49.45%E2%80%AFAM.png?w=960&amp;ssl=1 960w, https://i0.wp.com/www.gubatron.com/blog/wp-content/uploads/2025/01/Screenshot-2025-01-30-at-9.49.45%E2%80%AFAM.png?resize=300%2C172&amp;ssl=1 300w, https://i0.wp.com/www.gubatron.com/blog/wp-content/uploads/2025/01/Screenshot-2025-01-30-at-9.49.45%E2%80%AFAM.png?resize=768%2C441&amp;ssl=1 768w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p>You can then configure your github client and repo to use that key to sign in two ways.</p>
<ol>
<li>On the command line</li>
</ol>
<pre>$ git config [--global] gpg.format ssh
$ git config [--global] user.signingkey ~/.ssh/id_rsa.pub
$ git config [--global] commit.gpgsign true
</pre>
<ol>
<li>On the repo&#8217;s .git/config file</li>
</ol>
<pre>[user]
        name = gubatron
        email = gubatron@gmail.com
        signingkey = /Users/gubatron/.ssh/id_rsa.pub
[github]
        user = gubatron
[gpg]
        format = ssh
[commit]
        gpgsign = true
</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4122</post-id>	</item>
		<item>
		<title>Makefile for rust projects</title>
		<link>https://www.gubatron.com/blog/makefile-for-rust-projects/</link>
		
		<dc:creator><![CDATA[gubatron]]></dc:creator>
		<pubDate>Thu, 30 Jan 2025 04:05:44 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[rust]]></category>
		<guid isPermaLink="false">https://www.gubatron.com/blog/?p=4119</guid>

					<description/>
										<content:encoded><![CDATA[<p><script src="https://gist.github.com/gubatron/87a0440852367eaeacd9f0ad0da1e9df.js"></script></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4119</post-id>	</item>
	</channel>
</rss>