agent simulation · simgents · ongoing
We are building a synthetic economy where language models make weekly life decisions — work, rest, study, quit, spend — inside guard rails strict enough to keep them honest. Two identical cities run in parallel, with one receiving 1,000 units a month, and the other receiving nothing. Here's how we've designed it, and why almost all of the engineering effort went into stopping the models from telling us a good story.
Design document v0.1 · March 2026 · Pre-academic public presentation draft — not for citation
status — ongoing work
This page documents the design of the simulation, not its results. The engine runs, but no full 24-month run has been completed and published yet. Every figure below describes how the model is built, though none of it should be read as an outcome yet. When results exist, they will be published here alongside a public sandbox. Check back soon, or subscribe at the bottom of this page.
§ 1 — the question
Real basic income pilots are expensive, slow, and politically fragile. Stockton ran for 24 months with 125 people. Finland ran for two years with 2,000, and Ontario ran with 4,000 participants for about 20 months before being cancelled. Each one answers a narrow question about a specific population in a specific place, and each one takes years to produce a result. And there's no way to re-run them with a different stipend amount to see what would have happened.
A simulation can be re-run, and that's the motivation. The central question is: when a baseline monthly stipend is introduced into an economy already in motion, how does behavior shift across employment, health, spending, education, and business formation?
Note what's out of scope. This simulation says nothing about how a basic income would be funded or whether it is fiscally sustainable. That question is treated as an externality (maybe for another experiment). The stipend is simply present as an income line. The experiment starts after the policy has already been decided and targets what happens to the population after. The question is not how we fund the program, but what the results might be afterwards, and whether or not we even should.
These are drawn from the findings of real pilots (e.g. Stockton, Finland, and the three-year OpenResearch study). Listing these in advance is a small guard against reading whatever we want into the output later.
Recipients won't show reduced employment motivation. They may be more likely to pursue upward moves (school, a job change, a business) because the downside of trying is smaller.
Recipients will show higher average energy over time, because the stipend buys goods and services that aid recovery.
Increased spending will land on lower- and mid-tier goods before luxury goods, matching the OpenResearch finding that recipients spent primarily on basic needs.
Concentrated spending in the treatment city may push merchant prices up, testing whether a basic income creates local inflation pressure.
Recipients will show higher rates of school enrollment, graduation, and business formation over the 24-month window.
§ 2 — the bias problem
This is the part of the project that consumed the most design effort. Hand a language model an open-ended prompt that says live your life, and it will probably not behave like a real person. It will behave like a character in a novel.
There are three distinct failure modes here, and they compound.
Language models are trained on human-authored text, and human-authored text is selected for being interesting. Agents dramatize. They quit jobs, launch ventures, and spiral into crisis at rates far above real population base rates. Ordinary weeks, which are most weeks, get written out.
Models carry latent priors from their training data. An agent receiving a stipend may be steered toward a positive arc not because its personality and circumstances support it, but because the model has absorbed the cultural argument that basic income works. A model that absorbed the opposite argument is equally contaminating. Either direction destroys the experiment.
Absent explicit rules, a model optimizes for a satisfying story rather than a statistically plausible life. Given the freedom to decide its own consequences, it will grant itself the outcome the narrative wants.
Every serious attempt at agent-based economic simulation with language models has run into the same problem and reached approximately the same conclusion. EconAgent, presented at ACL in 2024, added perception and memory modules with explicit rule constraints and reported more realistic decision-making than either rule-based or learning-based approaches alone. The LLM Economist framework instantiated its agents from census-calibrated demographic data specifically to constrain personality diversity. ABIDES-Economist grounded agent heterogeneity directly in the economic literature rather than letting the model invent it.
The shared lesson is that the interesting capability of a language model in this setting isn't its judgment about consequences. It's its ability to make a plausible choice given a situation, at scale. So we give it constraints, and reduce its choice vector.
The model provides the decision. The engine defines the option space and enforces every consequence.
The single design principle everything else follows from
§ 3 — guard rails
Each layer narrows what the model can do. By the time a decision is actually made, the space of possible answers is small, legal, and weighted toward what someone with that personality in that situation would plausibly choose.
Six trait scores, drawn from a calibrated normal distribution, mathematically weight every available option before the model is ever called. A moderate agent is unlikely to be offered a dramatic path.
Each agent occupies exactly one of eight discrete states. The state determines which options appear in the prompt at all. An enrolled student is never shown “enroll in school” again.
The model returns a JSON object with one choice letter and a short reasoning string, validated before anything is written. It cannot propose new options or alter the schema.
Every change to energy, savings, and life satisfaction is computed by deterministic formulas in the engine. The model's only contribution is selecting which path is taken.
The stipend is presented as a factual income line with no normative language. Both cities receive identical prompt templates; only the data fields differ.
What "structured output only" actually looks like — the schema every weekly decision is validated against before it can touch the database:
the entire contract between model and engine
class AgentDecision(BaseModel): choice: Literal["A", "B", "C", "D", "E"] reasoning: str # max 300 characters| Control | Prevents |
|---|---|
| Multiple choice only | Dramatic narrative bias — the model cannot narrate free behavior |
| State machine gating | Logical incoherence — impossible options never appear |
| Neutral stipend framing | Political priors leaking into decisions |
| Identical prompt templates | Systematic prompt-level differences between the two cities |
| Personality pre-weighting | Over-dramatization of otherwise ordinary agents |
| Engine-enforced outcomes | The model negotiating or softening its own consequences |
| Reasoning logged, never acted on | Stated justifications overriding the rules |
Even with every guard rail in place, this produces internally consistent behavior from a simplified synthetic population. Its value is in the direction and relative magnitude of the difference between the two cities, not in predicting real outcomes for real people. This is a simulation, not a crystal ball.
In fact, its closer to a calibrated game than an econometric study. Results should be treated as hypothesis-generating, never hypothesis-confirming. Anything approaching a publishable claim would require peer review of the simulation rules themselves, multiple independent runs across different random seeds, and sensitivity analysis on every constant named on this page.
§ 4 — two cities
Two cities run in parallel with the same population distribution, the same employers, the same merchants, and the same schools. Random seeds are set so that both populations produce statistically equivalent trait distributions, verified at initialization before any decision is made.
City A — control
No stipend
100 agents. Standard economic mechanics. Income comes from wages, business draws, or nothing at all.
City B — treatment
1,000 / month
100 agents. Every agent receives an unconditional stipend from month one, regardless of employment, savings, or any other factor.
Loosely calibrated against US occupational data and intentionally simplified. The 10% unemployment rate sits in the range observed in OECD countries under economic stress, and gives us a meaningful population of precarious agents to study.
The five employers each start with a funded business. Their employee slots are pre-filled from the worker population at roughly 70% capacity, leaving eight to ten open positions per city — a tight but not frozen labor market.
The stipend is income, not a starting asset. Both cities begin with identical savings, enough to weather a few bad months, but not enough to absorb sustained unemployment.
Twenty-four simulated months covers one full vocational program, one university degree, and several rounds of business formation and failure.
§ 5 — personality
Agent differentiation uses the Big Five: Openness, Conscientiousness, Extraversion, Agreeableness and Neuroticism. This is the most empirically validated personality taxonomy available, and one with decades of published work linking specific traits to specific financial and occupational behaviors. That literature is the whole reason for choosing it. A bespoke trait list would have been easier to design and impossible to cite.
One trait is added beyond the standard five: ambition. Conscientiousness captures self-discipline and rule-following, while ambition captures goal-directed upward striving — the propensity to chase a promotion or start something new even under adversity. Occupational psychology treats these as separable, and in this simulation ambition is the primary modifier on every decision involving upward mobility risk.
Expected agents per 100 at each score. Generated from a normal distribution with mean 10 and standard deviation 3, rounded and clamped to the range 1–20.
A flat roll across 1–20 would hand roughly five agents per city a score of 1 and five a score of 20 on every trait. That over-populates the extremes and fills the city with caricatures. A normal distribution puts about 68% of scores between 7 and 13 and only a fraction of a percent at the edges, which is what psychological traits actually look like in a real population.
score generation
the same formula, as it runs
score = int(round(numpy.random.normal(10, 3)))score = max(1, min(20, score))Every mapping is anchored to a published finding. Where the literature is thin, the mapping is deliberately weak.
| Trait | Drives | In the simulation | Basis |
|---|---|---|---|
| Openness | Career risk, entrepreneurship | Each 2 pts above 10 adds weight to school enrollment, job switching, and business formation. Below 5, an agent will not start a business at all. | Zhao & Seibert, 2006 |
| Conscientiousness | Savings discipline, rest quality | High scores shift spending toward budget tier and improve weekly energy recovery. Low scores drive impulse purchases. | Nyhus & Webley, 2001 |
| Extraversion | Social spending, job access | High scores raise mid-tier and luxury spending weight, and add a bonus toward reaching higher job tiers — a networking proxy. | Brown & Taylor, 2014 |
| Agreeableness | Hiring, firing, quitting | High-agreeableness employers need a longer streak of poor performance before firing. High-agreeableness workers tolerate worse jobs for longer. | Barrick & Mount, 1991 |
| Neuroticism | Energy drain, retail therapy | High scores reduce weekly recovery, increase unemployment stress drain, and raise discretionary spending weight even when savings are low. | Brown & Taylor, 2014 |
| Ambition | Upward mobility | The sixth trait, added beyond the standard Big Five. Primary modifier for enrollment, promotion attempts, and the post-graduation job lottery. | Judge & Kammeyer-Mueller, 2012 |
None of these profiles are hardcoded. They emerge from applying each trait modifier independently and watching what happens when two of them point the same direction.
High neuroticism + low conscientiousness
Fast energy drain, impulsive spending, weak savings discipline. These agents reach hospitalization thresholds more than any other group.
High ambition + high openness
Strong pull toward school and business formation — and a matching energy drain from chronic overcommitment.
High conscientiousness + low extraversion
Budget spending and consistent savings growth, but little networking benefit when it comes to job advancement.
High agreeableness + low conscientiousness
Tolerates bad employment far too long and accumulates energy debt before finally quitting.
§ 6 — the economy
Every agent carries an energy score representing physical and psychological capacity. This is cumulative, not a weekly reset. Chronic overwork depletes it faster than rest recovers it, and hitting zero means hospitalization.
This was a deliberate choice, because a resetting energy bar would erase the long-term consequences of sustained overwork and poverty, which is what the research question is about.
Recovery minus drain. Anything below the zero line is on a trajectory toward collapse; the only question is how many weeks it takes.
—Full-time workers at every income level are in deficit without spending on recovery goods. This is intentional, as it establishes that income which enables spending is health-sustaining.
—The stipend never restores energy directly. It provides income that enables mid-tier spending, which narrows the gap without closing it.
—Employers face the steepest drain of anyone. Running a business is the highest-risk path in the simulation.
—The unemployed recover energy while their savings evaporate. That is the central trap: rest preserves your health and costs your money, work earns money and costs your health.
the bar chart above, as a formula
weekly_net_energy = base_recovery + c_bonus - n_penalty + spending_bonus - work_drain - study_drain - stress_drain - poverty_drainA low-income wage of 3,500 was set to match the base monthly expense of 3,500 precisely. A full-time worker at the bottom of the ladder generates no savings at all before discretionary spending. That mirrors the real condition where a single minimum-wage income covers housing and essentials and nothing else.
| Role | Hours | Monthly | Surplus after expenses |
|---|---|---|---|
| Part-time | ≤ 20h | 1,750 | −1,750 |
| Low-income | 40h | 3,500 | 0 |
| Mid-income | 40h | 5,500 | +2,000 |
| High-income | 40h | 8,000 | +4,500 |
| Unemployed | — | 0 | −3,500 |
This is the single most important number in the model. A stipend of 1,000 converts a low-income worker from an agent with zero buffer into one who can afford two weeks of mid-tier spending per month, which unlocks the energy recovery bonus that drives the health hypothesis. The entire causal chain runs through this row of the table.
It is recalculated monthly and collected purely as a measurement. It never feeds back into decision behavior, which keeps it clean as a wellbeing metric.
The weighting follows the components of the OECD Better Life Index, which identify health and financial security as the strongest predictors, followed by work quality and social relationships.
Three merchant tiers per city. They make no model calls. They exist as spending destinations and as the mechanism for testing whether concentrated demand creates local inflation.
Prices move 5% per month when demand at a tier shifts more than 20% either way, floored at 80% and capped at 150% of the original. If the treatment city drives prices above the control city, that divergence is the inflation result.
life satisfaction, recomputed monthly
§ 7 — the weekly loop
Every agent is always in exactly one of eight states. The engine owns those states and every transition between them. The model only makes choices within whatever the current state permits.
Without this, an agent that enrolled in school last week could be offered enrollment again the following week (and might even agree). State is what makes a life coherent across a hundred and four decisions.
Unemployed
No income. Can apply, enroll, or start something.
Part-time
Up to 20h. Can coexist with student.
Low income
40h at 3,500 a month.
Mid income
40h at 5,500 a month.
High income
40h at 8,000 a month.
Student
Enrolled. Tracks program and month.
Employer
Running a business with its own savings pool.
Hospitalized
Out for 8 weeks. No decisions, no expenses.
Options that are impossible are not down-weighted or discouraged in the prompt. They're absent from it.
Student — trade program, month 4 of 12
offered
never shown
Low-income worker — business #3
offered
never shown
Employer — business #2, three employees
offered
never shown
Nothing here is written by a human at runtime. The template is fixed; only the data changes. Note that the consequences are printed alongside each option. That is, the model is told exactly what each choice costs before it picks, and it has no ability to alter those numbers afterwards.
what the engine sends
--- YOUR CURRENT SITUATION ---Status: Student — Trade/Vocational, Month 4 of 12Energy: 612/1000Savings: 2,340Life Satisfaction: 4.8/10.0 --- RECENT HISTORY (last 4 weeks) ---Week 13: Chose "Study full intensity" -> Energy -105, tuition -250Week 14: Chose "Study + part-time work" -> Energy -172, Savings +700Week 15: Chose "Rest week" -> Energy +150, tuition -250Week 16: Chose "Study + part-time work" -> Energy -172, Savings +700 --- LIFE EVENTS ---Month 2, Week 7: Enrolled in Trade/Vocational programMonth 1, Week 2: Quit low-income job at Business #3 --- THIS WEEK'S OPTIONS ---A) Study full intensity (35h) — Energy: -105, Savings: -250B) Study + part-time work — Energy: -172, Savings: +450 netC) Rest week — Energy: +150, Savings: -250D) Drop out of school — Status -> Unemployed; no further tuition Choose one option. Respond ONLY in JSON.And the only thing that comes back:
what the model returns
{ "choice": "B", "reasoning": "Savings are declining with 8 months left; the part-time income avoids running out before I finish."}The response is validated against a strict schema before anything is written to the database. If it fails or names an invalid letter, the engine retries once and then falls back to the highest-weighted option for that agent. The reasoning string is logged verbatim for qualitative analysis and has no mechanical effect. It's a window into the decision, and humanizes it for the audience, but it's not part of its mechanism.
Passing the full 104-week history into every call would cost roughly thirty times more and buy almost nothing. The current status line already encodes the long arc — "student, month 4 of 12" says everything about the trajectory. Four weeks is enough to capture behavioral momentum and stop week-to-week flip-flopping. Milestones are preserved separately as compressed life events.
| Approach | Tokens per call | Continuity | Cost per run |
|---|---|---|---|
| Full 104-week history | ~9,300 | Perfect | ~$160 |
| Rolling 4-week window | ~320 | Sufficient | ~$5 |
| No history | ~0 | Incoherent | — |
§ 8 — architecture
The system is deliberately boring. All of the interesting design lives in the rules, not the infrastructure. Nothing here needs to be clever — it needs to be reproducible.
Browser
Next.js · React · Tailwind
API
FastAPI · WebSockets · APScheduler
Simulation engine
Python · Pydantic
Persistence
PostgreSQL · SQLAlchemy
Personality generation happens once per agent and benefits from a stronger model. Weekly decisions happen twenty thousand times and need to be cheap. Splitting them keeps the profiles rich and the run affordable.
Weekly decisions
GPT-4o mini
~19,200 calls per run
Picks one letter from a pre-built menu and writes a short justification. Reliable structured JSON at a very low per-call cost.
Personality generation
Claude Sonnet
200 calls, once
Turns six trait scores into a name and a coherent backstory the cheaper model can then reference all run long.
Every mechanic on this page ultimately gets called from somewhere inside this shape — months containing weeks, weeks containing parallel decisions, months closing with expenses, stipends, and price updates.
simulation/engine.py — outer loop
for month in range(1, 25): for week in range(1, 5): decisions = await asyncio.gather(*[ call_llm(build_prompt(agent)) for agent in active_agents ]) for agent, decision in zip(active_agents, decisions): apply_outcome(agent, decision.choice) deduct_base_expenses() pay_ubi(city_b_agents) update_merchant_prices()The engine can complete a full 24-month run in roughly half an hour. It does not. The scheduler advances one simulated week per real day, so a full run unfolds over about six months of wall time, and the decision feed trickles out across each day.
This is for the audience, not the science. Watching two hundred lives play out slowly, in something adjacent to real time, is a fundamentally different experience from reading a summary table after the fact. The batch mode still exists for the analytical runs — where you want thirty seeds, not a story.
§ 9 — cost & scale
This is the part that makes the whole approach worth pursuing. Stockton cost millions and produced one result. A full run here costs less than a sandwich, which means it can be run again with a different stipend, a different population, or with a different seed, as many times as the question requires.
Token cost only, using the recommended split of a cheap model for decisions and a stronger one for personality generation.
The default configuration of 200 agents is highlighted. Cost is not the binding constraint at any of these sizes — latency is. At two hundred agents with twenty concurrent calls, each simulated week takes about twenty seconds of compute. A thousand agents pushes a full run to roughly ninety minutes, which is still tractable.
per-run cost, in full
~$20
Three full runs
One primary plus two sensitivity runs at different stipend amounts
~$30/mo
Infrastructure
Hosting, managed Postgres, and the frontend — the ongoing cost
~$200
Total research phase
Six months of infrastructure plus every run and test we expect to need
§ 10 — the playground
A single published result invites exactly one response: but what if you had chosen different numbers? The honest answer is to let people choose them. We are building a public playground where anyone can configure a run, start it, and watch two hundred agents live through it.
This also does something a published paper cannot. If you believe a stipend of 1,000 is too generous, you will be able to set it to 500 and see what changes. Disagreement becomes an experiment rather than an argument.
Stipend amount
0 · 500 · 1,000 · 1,500
The headline variable. Zero turns the treatment city into a second control — a useful sanity check on the whole model.
Population per city
25 · 50 · 100 · 200
Smaller populations finish faster and cost less; larger ones produce more stable statistics.
Duration
6 · 12 · 24 months
Twenty-four months covers a full university program. Six is enough to see early spending and energy effects.
Random seed
Any integer
The reproducibility control. Same seed and same config produces the same starting population every time.
Every decision as it happens, with the reasoning the agent gave. Agent #42 enrolled in trade school. Business #3 just went under.
Average energy, savings, employment rate, and hospitalization count for both cities, updated as the run advances.
Open any agent to see their traits, their full state history, and every choice they have made.
Where the two cities separate, when it starts, and which metric moves first.
Not open yet.
We want the analytics layer finished and at least one full run completed before opening this to the public. Subscribe below and we will tell you the day it goes live.
§ 11 — open questions
None of these are resolved in the current design. Listing them openly is more useful than discovering them in review.
A recovery of 150 per week against a drain of 5 per hour puts every full-time worker in deficit. That creates the stakes the model needs, but the exact numbers are an assumption, not a finding. A short pilot run should calibrate them before committing to the full design.
Right now one score carries both physical condition and psychological capacity. Splitting them would let us measure health effects properly — which happens to be the strongest and most consistent finding across real pilots. This is the most likely addition to the next version.
Contact happens only indirectly, through competition for job slots and through merchant prices. Job referrals, peer influence on spending, and community morale are entirely absent. A simple social graph where extraversion drives referral probability would be a start.
Employers pay fixed tier rates. In a real tight market they would bid up to attract and retain workers, which is exactly the mechanism through which a basic income might raise wages. Its absence is a meaningful gap.
Every agent currently pays 3,500 a month regardless of what they earn. Higher earners plainly spend more on housing and lifestyle. Fixing this matters if high-income agents accumulate implausible savings over 24 months.
At minimum: multiple independent runs across different seeds, sensitivity analysis on every constant, a pinned model version logged with the results, and peer review of the simulation rules themselves before the run rather than after. The first full run should be treated as exploratory.
A simulation can't tell us what a basic income would do for certain. It can tell us what our assumptions built up from past research and psychology imply.
That's a smaller claim than certainty, but no less useful. Making assumptions explicit, numerical, and runnable is how we find out which of them actually matter.
§ 12 — references
Barrick, M. R., & Mount, M. K. (1991). The Big Five personality dimensions and job performance: A meta-analysis. Personnel Psychology, 44(1), 1–26.
Brown, S., & Taylor, K. (2014). Household finances and the 'Big Five' personality traits. Journal of Economic Psychology, 45, 197–212.
Costa, P. T., Jr., & McCrae, R. R. (1992). Revised NEO Personality Inventory (NEO-PI-R) and NEO Five-Factor Inventory Professional Manual. Psychological Assessment Resources.
Diener, E., & Biswas-Diener, R. (2002). Will money increase subjective well-being? Social Indicators Research, 57(2), 119–169.
Hainmueller, J., Hall, D., Lundberg, I., & Marcus, J. (2023). UBI and health: Evidence from randomized experiments. NBER Working Paper.
Jorm, A. F., et al. (2000). Predicting anxiety and depression from personality. Journal of Abnormal Psychology, 109(1), 145–149.
Judge, T. A., & Kammeyer-Mueller, J. D. (2012). On the value of aiming high: The causes and consequences of ambition. Journal of Applied Psychology, 97(4), 758–775.
Kalleberg, A. L. (2011). Bad Jobs in America: Standard and Nonstandard Employment Relations and Job Quality in the United States. Russell Sage Foundation.
Karten, S., et al. (2025). LLM Economist: Large population models and mechanism design in multi-agent generative simulacra. arXiv:2507.15815.
Kiliyanni, A. L., & Sivaraman, S. (2016). Perception and reality of financial risk tolerance. MDPI Risks, 14(3), 71.
MIT Living Wage Calculator. (2023). Living wage by state and metropolitan area. livingwage.mit.edu.
Nyhus, E. K., & Webley, P. (2001). The role of personality in household saving and borrowing behaviour. European Journal of Personality, 15(S1), S85–S103.
OECD. (2020). OECD Better Life Index: Framework and Methodology. OECD Publishing.
Rao, A., et al. (2024). Evaluating the ability of large language models to emulate personality. Scientific Reports, 14, 31240.
SCORE Foundation. (2022). Small business financial performance benchmarks. score.org.
Steptoe, A., & Kivimäki, M. (2013). Stress and cardiovascular disease: An update on current knowledge. Annual Review of Public Health, 34, 337–354.
Urban Labs / University of Chicago. (2024). ORUS: OpenResearch guaranteed income study, September 2024 report.
Vohs, K. D., & Faber, R. J. (2007). Spent resources: Self-regulatory resource availability affects impulse buying. Journal of Consumer Research, 33(4), 537–547.
Warren, E., & Tyagi, A. W. (2005). All Your Worth: The Ultimate Lifetime Money Plan. Free Press.
Workforce Development Council / Stockton SEED. (2024). Stockton Economic Empowerment Demonstration: Final evaluation report.
Yang, S., et al. (2024). EconAgent: Large language model-empowered agents for simulating macroeconomic activities. Proceedings of ACL 2024.
Zhao, H., & Seibert, S. E. (2006). The Big Five personality dimensions and entrepreneurial status: A meta-analytical review. Journal of Applied Psychology, 91(2), 259–271.
This page summarizes an internal design document, version 0.1, dated March 2026. This is a pre-academic draft and should not be cited. Figures describe the construction of the simulation, not results from it. When a full run has been completed, the results and the raw data will be published here.
get involved
A simulation is only as good as the assumptions baked into it, and this one is full of them. Based on past research and literature, still assumptions nonetheless. The energy constants are guesses, the wage tiers are simplifications, and the decision menus encode a particular theory of how people behave under financial pressure. All of it is arguable, and we would like it argued over before we publish results rather than after.
If you work in economics, psychology, agent-based modeling, or have simply lived the conditions this model is trying to approximate, we want to hear where we may be wrong.
Tell us what we got wrong.
Critiques, calibration data, collaboration proposals, etc. are all welcome.
we are a registered Canadian non-profit.
donation information is soon to come.