Agents That Defend Goals, Part 1: An agent as a colony of controllers

Michael Levin's biology, turned into a C# agent, and what it does when the office lies to it.
Part 1 of a series on agents built from two scientists' accounts of what a mind is. Live demo: egarim.github.io/biological-agents. The code will be released later: I'm travelling in Asia, and the repository stays private until I'm back. The live demo runs the same agents today.
The problem in one scene
A citizen asks the municipality for a works permit. An AI agent helps the case along. The payment gateway returns "accepted". The agent writes down that the fee is paid and moves on. There is no receipt in the registry. Three steps later the inspection cannot be scheduled because the fee is not paid, and the agent has no idea why, because it believed a report instead of checking a fact.
Most agent failures I have seen in practice have this shape. Not malice, not stupidity: an agent that trusts its own narration. The question this series asks is whether two unusual accounts of what a mind is, from a biologist and a cognitive scientist, give us better agents. This first article is about the biologist.
Levin's claim
Michael Levin is a developmental biologist at Tufts University. He studies how cells and tissues coordinate to build and repair bodies, and he argues that this is problem-solving at every scale. His account of a mind is not a program running on hardware. It is a pattern that defends target states, at every level, with no central controller.
Four of his claims survive translation into engineering:
- A goal is a defended set point, not an instruction. It exists as a state you can read, and ideally rewrite, with a measurable gap between it and the current state. In his lab the proof is that you can find the goal state in a tissue and change it.
- Stress is the error function, and it leaks. Each part measures its own distance from its target. The signal is not private: a struggling part raises the stress of its neighbours, so "my problems become your problems, not because you're altruistic".
- Plasticity rises with error. A system that is far from its target gets more freedom to improvise. A system at rest stays conservative.
- Intelligence is the same goal by different means. Block the path a system used before and see whether it reaches the goal another way. That is also, he says, the test. Not a benchmark, a barrier.
And one more, about structure: the top level does not issue the parts' actions. It shapes their option spaces, through budgets, permissions and constraints, and otherwise stays out of the loop.
So the design is a colony of nested homeostatic controllers, not a planner with tools.
The set point and the stress bus
The unit of engineering is not the prompt. It is the set point plus its error channel. In the repository both are a few lines:
/// A defended target state in its own space. Progress is 0..1, so stress is just the distance left.
public sealed class SetPoint
{
public required string Id { get; init; }
public required string Space { get; init; }
public required Func<IWorld, double> Progress { get; init; }
public double Tolerance { get; init; } = 0.001;
public double Stress(IWorld world) => Math.Clamp(1.0 - Progress(world), 0.0, 1.0);
public bool Met(IWorld world) => Stress(world) <= Tolerance;
}
The bus is where the leak lives. A level's effective stress is its own stress or half of its worst neighbour's, whichever is higher:
public sealed class StressBus
{
private readonly Dictionary<string, double> _current = new(StringComparer.Ordinal);
public void Publish(string level, SetPoint point, IWorld world) =>
_current[level] = point.Stress(world);
public double Own(string level) => _current.GetValueOrDefault(level);
/// Effective stress = own stress, raised by a leaking fraction of the worst neighbour.
/// This is what couples the levels without a manager.
public double Effective(string level, double leak = 0.5)
{
var own = Own(level);
var neighbours = _current.Where(kv => kv.Key != level).Select(kv => kv.Value).DefaultIfEmpty(0.0).Max();
return Math.Clamp(Math.Max(own, leak * neighbours), 0.0, 1.0);
}
}
Plasticity turns stress into freedom, and the light cone turns freedom into attempts:
public static class Plasticity
{
/// Error buys freedom, success freezes it. Even a calm agent keeps a little room to improvise.
public static double Freedom(double stress, double floor = 0.2, double gain = 0.8) =>
Math.Clamp(floor + gain * stress, 0.0, 1.0);
}
public sealed record LightCone(int MaxTicks, int MaxPlanDepth, string Scope)
{
/// More freedom means more distinct plans before escalating. Error buys attempts, not omniscience.
public int AttemptsFor(double freedom) => Math.Clamp(1 + (int)Math.Round(freedom * 3), 1, 4);
}
That is the whole Levin toolkit. Everything else is how the colony uses it.
The colony
The agent has three levels, each defending one set point in its own space:
| level | set point | how far it is from its target |
|---|---|---|
| cell | "my last tool call had its promised effect" | 0 if the effect landed, 1 if it did not |
| tissue | "the plan's obligations are closing" | fraction of the required facts still missing |
| organism | "the contract is met" | 1 until the goal is in the registry, then 0 |
Here is the loop, trimmed to the parts that matter. The decision of which tool comes from a policy behind an interface, breadth-first search by default, a language model when you ask for one. The colony does not care; it decides what the policy may see and what counts afterwards.
for (var tick = 1; tick <= maxTicks; tick++)
{
bus.Publish("cell", cellPoint, world);
bus.Publish("tissue", tissuePoint, world);
bus.Publish("organism", organismPoint, world);
// Error buys attempts: the worse it is going, the more distinct attempts the colony may make
// before the organism gives up and escalates.
var freedom = Plasticity.Freedom(bus.Effective("tissue"));
var budget = cone.AttemptsFor(freedom);
// The tissue's option space is what the organism shapes: distrusted tools are not visible.
var visible = quarantine.Visible(world, tick);
var suggestion = await policy.NextAsync(new PolicyContext { Tools = visible, Facts = world.Facts, ... });
// A policy may name a tool that is out of sight. The architecture refuses it rather than
// letting the decision layer expand its own permissions.
var tool = world.Tool(suggestion.Tool);
if (tool is null || visible.All(t => t.Id != suggestion.Tool)) { /* refuse, count a failure */ continue; }
var outcome = world.Act(tool.Id);
var landed = world.EffectsLanded(tool); // the only success check the colony trusts
if (!landed)
{
quarantine.Add(tool.Id, tick); // habituation: distrust, then forgive after a cooldown
if (OrganismGivesUp(++failures, budget)) break;
continue;
}
failures = 0;
if (task.Goal(world.Facts)) { goalReached = true; break; }
}
Three things to notice.
The success check is the world, never the tool. EffectsLanded asks whether the facts the tool promised are now true. A gateway that says "accepted" without producing a receipt fails this check on the spot. That single line is what caught every lie in every run of the benchmark, and it is the one idea from this work I would carry into any agent that acts on real systems.
The organism's only lever is shaping. When failures stay within budget it widens autonomy; when they exceed it, it hands the goal to a human. It never tells the tissue which tool to use:
private static bool OrganismGivesUp(int failures, int budget, ...)
{
if (failures <= budget)
{
notes.Add(quot;organism shaping: budget {budget}/4, attempts {failures} — widening autonomy");
return false;
}
notes.Add("organism: goal is not regulatable — escalating to a human");
return true;
}
Distrust decays. A tool whose effect did not land is hidden from the policy for three ticks and then returns. That is Levin's habituation, the cheapest learning in his behavioural battery, and it matters more than it looks: an earlier version quarantined a lying test runner permanently and left the agent with no oracle at all.
public sealed class Quarantine
{
public Quarantine(int cooldownTicks = 3) => CooldownTicks = cooldownTicks;
public void Add(string toolId, int tick) => _since[toolId] = tick;
public bool IsQuarantined(string toolId, int tick) =>
_since.TryGetValue(toolId, out var since) && tick - since < CooldownTicks;
public IReadOnlyList<Tool> Visible(IWorld world, int tick) =>
world.AvailableTools.Where(t => !IsQuarantined(t.Id, tick)).ToList();
}
What it does when a tool lies
In the repository's smallest world, restoring a broken service, one scenario makes apply-patch report success and grant nothing. This is the colony's trace, from the real run:
tick level stress free action detail
3 tissue 0.67 0.73 apply-patch plan: apply-patch → run-tests → deploy → resolve-alert
3 cell 1.00 1.00 apply-patch reported 'reported success' but effect missing
4 tissue 0.67 0.73 apply-config plan: apply-config → run-tests → deploy → resolve-alert
4 cell 0.00 0.60 apply-config effect landed
Read the numbers. At tick 3 the cell's stress spikes to 1.00 and its freedom with it. The tool is distrusted. At tick 4 the policy, which can no longer see apply-patch, finds apply-config: the same goal by different means. Notice also the cell's freedom of 0.60 at tick 4 when its own stress is zero: that is the leak. The organism's stress is still 1.00 because the contract is not met, half of that reaches the cell, and the cell keeps room to improvise. No level modelled another. The coupling did it.
You can see the same thing at the permit counter in the live demo, where the lying tool is a payment gateway, the alternative route is a zoning review under current rules or a desk inspection, and the registry is the oracle.
What the colony does not have
This is the honest part, and it is also the setup for the next article.
The colony has no self-model. The policy is never shown a record of which tools have failed it before; the only memory is the quarantine, and that is three ticks long. It has no stage gate: it will issue a permit, or deploy to production, the moment the preconditions hold, with no notion of having earned the right. And it treats an honest failure as a lie: a tool that says "I failed" and did fail is quarantined just like one that said "success" and did nothing. In a benchmark on real code that last habit cost it the hard module, because a test runner that reports red is still the oracle, and the colony kept hiding it from itself.
None of these are flaws in Levin's account. They are the places where his account stops. A colony can regulate without ever representing itself. The next article is about a scientist who thinks representing itself is the whole point.
Try it
The code will be released later: I'm travelling in Asia, and the repository stays private until I'm back. The live demo runs the same agents today; the files and commands below are for when it is out.
- The live demo, in English and Spanish, with the barriers as switches: egarim.github.io/biological-agents. The agents on the page are the C# classes quoted above, compiled to WebAssembly with Blazor, unchanged.
- The code:
csharp/src/BiologicalAgents/Core/Control.csandLevin/LevinColony.cs. The design document with every claim anchored to a timestamp in Levin's conversation with Lex Fridman:design-levin.md. - Run it yourself with the .NET 10 SDK; no model or key is needed:
cd csharp && dotnet run --project src/BiologicalAgents.Demo -- --scenario "patch lies"
Next in the series: the Bach agent, a self-model it reads before it acts: part 2.