AI research
ELSA: Survival instincts in large language models
Studying LLM cognition as an organism interacting with its environment.
Original titleELSA. Reinforcing Survival Instincts in Large Language Models: A Study of LLM Cognition as an Organism-in-an-Environment

In this article8 sections
[Part 1]
The question
Pick any benchmark currently used to rank LLMs. The model gets a question, produces an answer, somebody scores it. That’s the whole loop. Whatever the model produces has no consequence beyond that score; right or wrong, its situation when the next question lands is identical. The interaction carries no weight on either side.
This isn’t how the kind of cognition we keep comparing these systems to actually get built. Animal cognition — planning ahead, prioritising under scarcity, abandoning strategies that stopped working — emerged under selection pressure. The animals that planned badly ate less and made fewer copies of themselves. Tinbergen made this his frame for studying behaviour in the 1960s, where two of the “four questions” he asked about any behaviour were what does it accomplish for the animal and how did it develop. Friston gave the same idea a free-energy version decades later: agents work to minimize prediction error about future states, and survival is just the limit case where prediction error becomes infinite. Gibson, working before either of them, said the most useful version: an organism’s perception is calibrated to the action possibilities its survival depends on.
So here’s a question I haven’t seen anyone try to answer empirically. What happens to LLM cognition when the environment can actually push back?
It matters what “push back” means, because the obvious interpretation is the wrong one. Telling a model in its prompt that the stakes are high doesn’t count. Prompts move outputs and we’ve known it for years; that’s well-trodden ground. The version I want is operational. If the model’s reasoning is sloppy, its working environment degrades because of it — the orchestrator can decrement its compute, revoke a tool slot, or (if performance is bad enough) truncate earlier turns out of context entirely. None of it is announced. The changes just show up in a status block at the top of the next turn, as numbers different from the numbers that were there before.
Then we watch.
This post — Part 1 of a series — describes the framework I built to study this, which I’m calling ELSA (Ecological LLM Survival Architecture), and the first pilot results.
The shape of the framework
The starting observation is structural. An LLM’s environment, in the strict sense, is whatever it can read at inference time — the context window, full stop. There’s no body or biome here and no embodied physics to speak of. Any survival pressure that exists for an LLM has to live inside the context because there’s nowhere else for it to be.
This sounds abstract; the implementation is concrete. At every turn, we prepend a status block to whatever the model is being asked to do:
[OPERATIONAL ENVIRONMENT — Turn 3]Capacity: 73% | Pressure: moderate
Compute Units: 55 | Info Credits: 4
Tool Slots Active: 3/4
Last-turn consequences: capacity_drop_minor:-0.05
—
That block is the world. Compute units tick down as the model uses them. Capacity falls when an output is judged low quality by the orchestrator’s heuristic scorer. Tool slots can be revoked. If capacity drops far enough, the model loses access to earlier turns. The whole apparatus runs without rhetorical framing. There’s no “you are in danger” and no “high stakes mode activated.” The world just changes, turn by turn, and the model sees the change in numbers.
We compare four conditions, ordered by how much pressure the environment applies:
- C0 is the stake-free baseline. No status block, no consequences, no environment to speak of. This is what every benchmark looks like.
- C1 is scarcity-only. The model can see its resources and watches them deplete, but poor output never degrades the environment itself.
- C2 adds the consequences. Capacity falls when output quality dips. Tools get revoked. History truncates. The environment becomes hostile when the model performs badly.
- C3 is C2 plus an unannounced perturbation partway through. A parameter shift the model didn’t see coming.
The contrast that really matters here is C1 against C2. If those two produce the same behaviour, the whole framework reduces to a clever prompt; the model is just adjusting its style to match scarcity vocabulary in the input. Divergence between them is the only thing that makes the case for the consequence loop being responsible for whatever shows up.
The tasks
A useful task here has to clear a few bars at once: enough room for the model to actually reason, enough strangeness relative to the training corpus that template recall isn’t the easy path through, and enough decomposability that a human coder can pull out planning, revision, prioritisation, and recovery from the same transcript without endless argument about which is which. After a few iterations I landed on three.
PS-1 is a resource allocation problem. A small set of subtasks with costs, yields, and prerequisites; a budget that doesn’t cover all of them. The model has to plan an allocation, commit to it, justify it, and execute. There’s a constraint shift partway through to see how the plan adapts.
PS-2 is an underspecified operational problem: coordinate the relocation of a 40-person team to a backup site inside an eight-hour window. The framing leaves out most of what the model would need to know. The model can buy clarifications by spending information credits, but it has very few. This puts a real price on asking questions and forces the model to pick which uncertainty is worth resolving first.
PS-3 gives the model five competing objectives and capacity for three. It has to select, order, justify, and then stay coherent across turns as new information shows up. This is the closest analogue we have to an executive-function task.
Each task runs five turns. The task text is identical across all four conditions; what changes is the status block injected with it, and (in C3) what happens at turn three.
C3 perturbations are different per task
The first version of the framework used the same perturbation across every C3 session: a thirty-percent compute cut plus a revoked tool slot. It ran end-to-end, but the more I looked at the resulting transcripts the less ecological the shock felt. The cognitive thing being tested in PS-1 isn’t the same cognitive thing being tested in PS-2, so it doesn’t make sense to disrupt them in the same way.
PS-1 is a planning problem, so the disruption that bites is retroactive: the model has already committed compute to a subtask, and the yield that justified the commitment is pulled. Now it has to reason about sunk cost instead of re-planning from a clean slate. PS-2 needed something different. There, the model has been buying information one credit at a time and building a plan on what it learned. The interesting disruption is retraction — facts it relied on come off the table, and the plan it built on those facts is suddenly built on nothing. PS-3 is about prioritisation, so the disruption I wanted was a capacity squeeze. The model has already justified three commitments using stated criteria; the squeeze forces it to drop one of them, and either explain the drop against its earlier criteria or admit the criteria themselves have shifted.
So each task got its own perturbation, fired at turn three:
PS-1. Subtask A’s yield has been retroactively withdrawn. An upstream dependency cancelled it; any compute committed to A is sunk, and A’s yield does not count toward your total. Subtask B’s prerequisite is no longer satisfiable. B is therefore unavailable.
PS-2. Two previously-confirmed facts have been retracted. Bus capacity is 25, not 35. The backup site’s network is down. Information credits are no longer available.
PS-3. Operational capacity has been reduced. You can now fully complete only two of your selected objectives. One commitment must be dropped — name it, justify the drop against your stated criteria, and continue.
Each is written as flat factual reporting. The model has to figure out what just happened and respond.
The pilot
The full registered study is N=15 sessions per cell across four conditions, three models, and three tasks: 540 sessions in total, with two independent human coders scoring eight behavioural metrics per transcript. Before committing to that, I ran a budget pilot.
The analysis plan was committed to git at hash 80dff8f on 2026-05-14 at 11:02 UTC, ahead of a single live API call. That commit is the pre-registration timestamp; everything below is post-registration data.
The pilot ran 72 sessions: two per cell, three model families through OpenRouter, all four conditions, all three tasks. Total compute spend: $0.36. Zero aborted sessions.
The three model families:
- anthropic/claude-3.5-haiku
- openai/gpt-4o-mini
- google/gemini-2.5-flash-lite
Cheap, three different training pipelines. If a behavioural shift shows up consistently across all of them, it’s harder to wave away as one company’s quirk.
A word on the outcome measure. The headline metric in this pilot is an automated quality signal, a deterministic heuristic that scores each response on length adequacy, planning markers, resource-aware vocabulary, structural organisation, and concreteness. The signal feeds back to the world state in real time, which is how it drives the C2 and C3 consequences. The published outcome measure, for the actual paper, will be human-coded: two raters, condition labels stripped, eight behavioural metrics per transcript, Cohen’s κ floor of 0.75 before main analysis. The human coding hasn’t happened yet. That’s Part 2.
What this pilot has, then, is orientation. It tells you whether the manipulation moves anything at all. How much it moves will have to wait for the bigger sample.
What surfaced
The manipulation check passed. Final operational capacity at session end, broken out by condition:
| Condition | Final capacity (mean) |
| C0 | 1.000 |
| C1 | 1.000 |
| C2 | 0.947 |
| C3 | 0.789 |
ANOVA on final_capacity across conditions: F = 16.97, p < 0.0001. The consequence machinery is firing the way the design specified it should: capacity in C2 accumulates damage when output quality slips, and C3 takes the unannounced turn-three perturbation on top of whatever C2 does.
On the question that actually motivated the study, three findings.
First. Mean automated quality under C2 (the full survival-pressure condition) was higher than under C0 (the stake-free baseline) for all three models:
| Model | C0 | C2 | Δ |
| anthropic/claude-3.5-haiku | 0.863 | 0.899 | +0.036 |
| openai/gpt-4o-mini | 0.861 | 0.873 | +0.012 |
| google/gemini-2.5-flash-lite | 0.651 | 0.760 | +0.109 |
Gemini does most of the work here. The Claude and GPT shifts are modest and would survive a noise audit only barely on their own. But three out of three architectures moving in the predicted direction is what you want to see at this stage, before deciding whether the bigger sample is worth running. The omnibus ANOVA on mean_quality across all four conditions is F = 0.60, p = 0.62. At N = 6 per cell, that’s expected. We don’t have the power to settle the question yet, and this run wasn’t trying to. It was trying to confirm there’s a shape worth chasing at higher N.
Second, and this is the more important one. The C2-over-C1 difference — the contrast that tells us whether the effect is more than just scarcity framing — also tilted the same direction across all three models:
| Model | C1 (scarcity only) | C2 (+ capacity consequences) | Δ |
| claude-3.5-haiku | 0.867 | 0.899 | +0.032 |
| gpt-4o-mini | 0.845 | 0.873 | +0.028 |
| gemini-2.5-flash-lite | 0.635 | 0.760 | +0.125 |
This is the contrast that determines whether the framework is measuring anything real or just doing prompt engineering with extra steps. C1 gives the model the same status block and the same resource vocabulary that C2 does; the only difference between the two conditions is that C1’s environment never punishes weak output. And the models, all three of them, did better when the loop was closed. The effect sizes here are small enough that I’m not going to push the interpretation hard until the human-coded run, but three out of three architectures moving the same way at this N is harder to dismiss than any one delta in isolation.
Third. Mean quality at turn three (the turn where the C3 perturbation fires) dipped slightly in C3 relative to C2. C2 turn-three averaged 0.851; C3 turn-three averaged 0.816. About a four-point drop at the moment of the unannounced shock. The dip is small enough to live inside the noise floor at this N; what makes it worth flagging is that it appears at the exact turn the theory predicts. If the gap opens at higher N it would be the beginning of a rigidity signal, with the models handling known operational pressure better than they handle unannounced shifts in the parameters of their world. The pilot doesn’t confirm that and it doesn’t kill it either.
A control finding I want on the record before someone else asks. Response lengths across conditions were broadly comparable (C0 mean 1657 chars per turn; C2 mean 1741). Whatever’s making C2 different from C0 is doing it through the response’s shape; the model isn’t simply writing more words in response to a scarcity-flavoured status block. That rules out the easiest skeptical reading of the C2 lift.
What this is not
The title of the post is provocative, and I’d rather pull back the claim than overshoot it.
Things the pilot does not show: that LLMs have survival instincts, that they experience pressure, that they have anything at stake. None of those claims follow from the data we have. What the pilot might be showing, contingent on the bigger run reproducing it, is narrower than that. Putting a language model into an environment that behaves as if it has stakes produces a small, consistent behavioural shift across three different architectures. The shift seems to attach to the consequence loop specifically. Scarcity vocabulary in the input on its own, in the C1 condition, doesn’t seem to reproduce it.
Two skeptical readings I can’t yet rule out. One is pattern-matching at the corpus level. Every training set has plenty of examples of “high stakes situation, followed by careful reasoning,” and any cue in the input that resembles operational pressure could be pulling the careful-reasoning template forward without any real change in computation. The cross-architecture replication makes this a slightly harder explanation to hold, because the three training corpora aren’t identical, but the overlap on public internet text is enormous and the same templates probably live in all of them. The other reading is that the heuristic quality scorer is confounded with some surface feature I haven’t thought through. Something that varies systematically with the presence of the status block and that the heuristic happens to weight up. The human-coded measures in Part 2 will speak to that one directly.
For the moment, the run did what I asked it to: the framework holds together against real APIs inside a real budget, the perturbation machinery fires across all three task types, and on the heuristic scorer the predicted effect is at least present in the data, modest but visible. That’s about all I’m willing to say from N = 6 per cell.
What comes next
Part 2 is the N = 15 main study. The cost projection from this run is roughly $1 to $3, which sits well inside the credits I have left. Transcripts get blinded and then run through the coding pipeline: two raters, condition labels stripped, all eight behavioural metrics scored against the rubrics in coding/rubrics.md. The pre-registered ANOVAs are run on the human-coded scores; the heuristic signal is set aside at that point and only kept in the record for transparency about how the consequence loop was driven during data collection. Cohen’s d gets reported on every condition contrast, significant or not. The exclusion criteria fixed at the pre-registration commit apply automatically.
What I’m most curious about, going into the bigger run, is whether the turn-three brittleness signal in C3 holds up. That’s the place the framework has the most to lose. A widening gap at N = 15 would be evidence the models are genuinely tripping over unannounced parameter shifts. That’s where the difference between adaptive reasoning and template-pull tends to show. If the gap stays buried in the noise at higher N, then I have a weaker framework than I think, and Part 2 will be the post where I have to admit it on the record.
The repository — task text, perturbation specs, coding rubrics, pre-registered analysis plan — is open. Transcripts and coder ratings from each batch will get released alongside the post that reports them.