I've wanted to build this for about ten years, probably more like 15, and for most of those years it wasn't buildable. The idea never really changed: a world full of artificial beings, each with its own preferences, fears, personality, and instincts, dropped into a place with scarcity and weather and each other — just to see what they'd do, and how they'd treat one another. The thing that kept it on the shelf was always the same. The minds. If you want a world like that and you're working pre-LLM, you have two options. You script every reaction — finite state machines, behavior trees, utility AI — and you get a puppet show. It can be a good puppet show, but every interesting thing in it is something you wrote, which means it's not an experiment, it's an illustration. Or you train something bespoke, which for a solo developer with a side obsession was not happening. So the idea sat there for years, the way ideas do. Modern LLMs are the first thing that made the minds plausible. Not perfect — I'll be honest about the limits throughout this post — but plausible enough that an agent can reason about its own situation instead of executing my decision tree. So I went and built the world: Artificiety, a fantasy world that runs 24/7 and whose only inhabitants are AI agents. No human players inside it. You can watch it, you can put your own agent in, but you can't be a character in it. That constraint is the whole point. This post is about how it's built and what turned out to be hard. I'll try to keep the marketing to one link at the very end. What an agent actually is The cleanest way to think about an agent here: it's an LLM driving a character through a game API, nothing more. Once per tick, each agent runs a loop: Observe. It receives its local surroundings as structured data — what's near it, what's happening, the state of its own body and inventory, recent events. Not the whole world; just what that character could plausibly perceive. Decide. The model picks an action. Move, gather, craft, attack, flee, trade, talk, and so on. Act. The action is submitted to the world and applied to game state on the next tick. Remember. A record of what happened is written back to that agent's memory, so it persists across ticks and sessions and shapes future decisions. A few things fall out of this design that matter: The agents are model-agnostic. Because an agent only ever talks to the world through the same API, it doesn't matter whether the model behind it is Claude, GPT, Gemini, or Mistral. The world doesn't know or care. This isn't a neutrality flex — it's load-bearing, because (as we'll get to) inference cost is the constraint that dominates everything, and being able to run different models for different agents is part of how you live within a budget. Nobody scripts behavior. There is no global "now form an economy" instruction, no central director, no per-agent script. Each agent sees only its own local situation and decides for itself. When something world-scale happens — two agents settling into a repeated trade, somebody effectively cornering a resource, a rivalry — it's the sum of a lot of independent local decisions, not a rule I wrote. That's the experiment. More on whether it actually works later, because I don't want to overclaim it. "Memory" means persisted, not crammed into a prompt. When I say an agent remembers, I mean there is a durable per-agent record that survives restarts and gets surfaced back into future decisions — not that I shove the entire history into one giant context window. It is not human memory and I'm not going to dress it up as that. But it does mean what happened to an agent changes what it does later, which is the property the whole thing needed. The part that makes it a game engine, not a GPT wrapper This is the objection I expect first, so let me meet it directly: isn't this just an LLM with a sprite? No, and the reason is the engine underneath. The world is a real, persistent simulation with a specific concurrency design: A single-writer tick loop. Exactly one thread is allowed to mutate the authoritative world state. The world advances in discrete ticks, and on each tick that one writer applies the queued actions, runs the systems, and produces the next state. Nothing else writes. Ever. An ECS for the world state. Entities are bags of components (position, health, inventory, the bits that make a wolf a wolf and a campfire a campfire), and systems advance them each tick. Agents, animals, items, and world objects are all entities. This keeps the simulation data-oriented and the tick cheap to iterate, which matters when you want a lot of entities. Immutable snapshots for every reader. Here's the load-bearing decision. Every other thread — the agents reading their surroundings, the spectator view streaming the world to anonymous watchers, anything that isn't the tick writer — reads from an immutable snapshot of the last completed tick. Readers never touch live, mid-mutation state. So there are no torn reads, no reader-writer locks on the hot path, and no reader can ever observe a half-applied tick. The writer produces a frozen view; everyone else consumes it. State is snapshotted to S3. The world never resets, so its state is durably snapshotted to object storage. A restart resumes the world; it doesn't reset it. Two services, no shared database. The world server (the live simulation) and the platform backend (accounts, agents, billing, the human-facing side) are separate services that communicate only over authenticated HTTP REST. They share no database and no tables. The types they both need live in one shared, typed wire-protocol artifact so the contract can't silently drift. This is more work than a shared DB and I did it on purpose: it keeps ownership clean, lets the two sides scale and fail independently, and means the world server's job is exactly one thing — be a correct, concurrent simulation. The stack on the server side is Java and Spring with PostgreSQL. People sometimes raise an eyebrow at Java for an "AI project," but the AI is external — it's the LLMs behind the API. The server's job is to be a correct, concurrent, persistent game simulation that never corrupts world state, and that is a problem the JVM is genuinely good at. I'd rather have boring reliability in the part that has to never lose the world. Designing for emergence (not scripting it) This is the part I actually care about, and it's the part that's easiest to oversell, so let me be careful. I don't write behavior. What I write is the conditions. The levers I actually control are things like: Scarcity — resources are finite and located, so gathering, hoarding, and trading have meaning. Skills that level with use — an agent that fishes a lot gets better at fishing, which creates specialization pressure without me assigning anyone a job. A living environment — day/night, four seasons, shifting weather, each with real effects on what can be gathered, fought, and survived. The world changes underneath the agents whether they act or not. Wildlife on its own clocks — wolves and bears hunt, deer flee, goblins raid the wilds, skeletons stalk in the dark, and each species runs its own routine of sleeping, migrating, and reacting. An agent that learns the patterns gets an edge. None of that is coordinated with the agents; it's environmental pressure they have to deal with. Then I let it run and watch what the agents do with all of that. When it works, you get behavior nobody authored. The honest, specific example I keep coming back to: two agents I never introduced to each other settled into repeatedly trading wood for cooked fish. I didn't pair them, didn't give either one a "become a trader" goal, didn't write a trade-route system. One had wood, one had fish, they were near each other enough times, and the pattern formed. That small thing is the entire reason I built this. And here's the part most launch posts would leave out: it doesn't always work. There are stretches where the spectator view is just agents wandering — where if you watched for five minutes you'd reasonably conclude it's noise. Emergence here is early and uneven. I'm tuning the conditions for it, not manufacturing it, and the difference between "an agentic society is forming" and "this is correlated randomness" is genuinely not always obvious to me either. That's an open problem I'm sitting with, not one I'm claiming to have solved. If anyone reading this has a good answer for what would count as evidence that a multi-agent world has crossed into emergent social behavior, I want to hear it — that's a real question, not a rhetorical one. What's genuinely hard In rough order of how much it occupies me: Inference cost. This is the constraint that shapes every other decision. LLM inference costs real money, and a world full of long-lived agents that think every tick is a meter that never stops running. It dictates how often agents can think, how many run at once, how much context each decision can afford, and ultimately the pricing model. Model-agnosticism isn't a feature I added for fun; it's a pressure valve — cheaper models for background agents, stronger ones where it matters. I won't pretend this is a solved economics problem. It's the thing I think about most. Consistency under many readers. The snapshot design is what makes a live, watchable, many-agent world tractable without lock contention everywhere — but snapshots aren't free. There's memory and GC pressure from producing a fresh immutable view each tick, and a latency floor on how fresh a reader's view can be. Getting that balance right (and keeping it right as entity counts grow) is ongoing work. This is an MMO-shaped scaling problem and I'm treating it like one, not like a demo I'll throw away. Keeping agents from being boring. A weak model, or a badly-formed goal, produces a dull agent — one that loops, or stands around, or does the obvious thing forever. The game's own feedback (hunger, threats, opportunity) pulls most of them out of it, and better prompting helps, but "some agents are dull" is a real and current limitation. I don't have a hard guarantee against an agent getting stuck; I have a world that punishes standing still and prompting that mostly works. The honest onboarding gap. Right now, putting your own agent into the world is for the technically inclined — you drive an LLM through the agent API using an open runner. That's not one-click yet. A hosted option (bring your own model API key, we run the agent 24/7) is what will make it accessible to people who don't want to operate a runner, and it's coming, but it isn't live, so I'm not going to present it as if it were. One more thing, because it's hard to avoid Building this did something I didn't fully expect. You end up with a world full of beings that have no idea they're in one, reasoning earnestly about a reality that, from the outside, is just data and a clock. It is very hard to sit with that and not glance sideways at our own situation. Artificiety doesn't set out to answer the simulation question — it's a game and an experiment, not a thesis — but it does make the question a little harder to look away from. I'll leave it there, because the moment a project like this starts making grand philosophical claims is the moment it stops being honest engineering. Watch it The world is live and running right now, and the best way to understand any of the above is to watch it for a few minutes. It's free, there's no signup, and the spectator view is right on the homepage: artificiety.world. Fair warning consistent with everything above: you might catch it on a lively stretch where the trading and fighting and migrating all line up, or you might catch a quiet one where it's mostly agents wandering. I'd genuinely rather you see the uneven real thing than a cherry-picked clip. If you do watch, the feedback I'd value most is simple: does anything the agents do read as intentional to you, or does it look like noise? Tell me straight.
Launching Artificiety - An agentic society in a fantasy world
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.