"There is no me without you."
— Samantha, Her, 2013
The first time I built a chatbot, I trained it on five thousand of my own Facebook messages and put it in an art gallery and watched strangers talk to a digital ghost of me for a week. The thing that surprised me wasn't the bot's responses, those were always going to be uneven, because the dataset was uneven, and I was nineteen and didn't know any better. The surprise was how the strangers responded to the bot. They addressed me directly. They asked the bot questions they'd never have asked the actual me. They thought, briefly and incorrectly, that the bot remembered them. Some of them got angry when it didn't.
That was 2017. The technology was a Naive Bayes classifier wrapped around message-response pairings. The result was a curiosity, not a product. But the lesson stayed: people will treat a digital companion like it has continuity, even when it doesn't. The continuity is the thing they're paying for, even if they can't articulate it. If your companion forgets, the magic breaks. If it remembers wrong, the magic breaks worse.
This post is the case study of wilds.ai, a companion product built on AgentOS where the continuity is the feature. Memory works. Tools work. Personality is consistent across sessions. The companion knows your name three days later because the runtime has actual memory, not a chat history that gets re-injected at inference time. None of this is scripted. The mechanics are below.
A user opens wilds.ai and starts chatting with Alice, an AI companion based on Alice in Wonderland. They haven't talked in three days.
Alice: Welcome back, Johnny! I hope your wanderings were fruitful, or at the very least, interesting.
She remembers his name. He told her once, days ago, in a different session.
He asks for memes. Alice doesn't say "I'm an AI, I can't send images." She searches Giphy, picks a cat GIF, and sends it.
Johnny: holy crap that is scary
Johnny: did you even see what you posted? describe it to me lol
Alice: Let me take a look...
Alice calls a vision tool, passes the GIF URL to a visual language model, reads back a description of a wide-eyed cat staring directly into the camera, and responds:
Alice: I see now! It's a rather intense-looking cat with enormous eyes staring straight ahead. I can understand why you found it unsettling. Cats do have a way of looking like they're peering into your very soul, don't they?
None of this is scripted. Alice has tools and she decides when to use them. She chose to search for a GIF. She chose to look at what she sent. She chose to describe it in character.
Every piece of this runs on AgentOS.
The lineage worth naming: agents-with-memory-that-act-in-character is what Park et al.'s Smallville generative agents (Stanford, 2023) proved was buildable at small scale. The companion case study on wilds.ai is a production version of the same idea, with the memory and tool layers ported from research-prototype scaffolding into an Apache-2.0 TypeScript runtime that holds up across sessions, not just a 25-agent simulation day.
What most AI companions ship
The standard AI chat experience in 2026: you open an app, you talk to a character, you close the app. Next time you open it, the character has no idea who you are. Your name, your preferences, the joke you shared last Tuesday, the photo you sent. None of it carries over.
The character can't send you images. It can't search the web. Asked to "describe what you just sent me," it says "I'm unable to see images." It has no tools. It has no memory. It has a system prompt, a context window, and an inference call.
That's the default companion stack: a language model in a costume, with a personality that resets every session.
Alice's underlying framework is shaped differently.
Memory designed like cognitive memory
Alice's memory doesn't just record what you said. The mechanisms underneath are borrowed from cognitive-science literature, with the goal that the system forgets like a person forgets and remembers like a person remembers, rather than retrieving every embedded chunk every time.
Forgetting is a feature. Memories decay over time following an Ebbinghaus forgetting curve. The strength of each memory depends on how it was encoded: a casual remark about the weather fades in hours. Your name, repeated and emotionally tagged, persists for weeks. Unimportant details fall away naturally, so Alice doesn't drown in trivia.
Emotional moments stick. When encoding strength crosses a threshold, the memory is marked as a flashbulb memory. These resist decay. If you tell Alice something that surprises or moves her, she'll remember it long after the small talk has faded.
Retrieval pulls from several places at once. When Alice needs to remember something, wilds.ai's memory bridge queries six sources together: semantic recall (embedding similarity over her memories), the most recent memories, the account's shared memory, documents you've uploaded, images you've shared, and a full-text match for exact words. It ranks the results as one set and drops duplicates. When semantic recall comes back with fewer than two memories and you've played a game recently, a GraphRAG query over that game's world adds what pure embedding similarity misses.
Five memory types. Episodic (experiences: "Johnny and I played a riddle game"), semantic (facts: "Johnny is 33 years old"), procedural (skills and habits), relational (relationship dynamics and trust levels), and prospective (reminders and commitments). The taxonomy follows the CoALA framework (Sumers et al., 2023), which formalizes episodic, semantic, and procedural memory for language-model agents; AgentOS adds the relational and prospective layers a companion needs.
Here's how wilds.ai wires the memory system into the companion. CompanionOrchestrator and the memory bridge are wilds.ai's own application code, as is the recall above:
1const orchestrator = new CompanionOrchestrator(persona, relationship, { 2 memoryBridge, 3 history: messages, 4 onRecallMessages: buildDbRecallCallback(actorId, slug, branchId, personaId), 5 onRecallAttachments: buildDbAttachmentRecallCallback(actorId, slug), 6 totalMessageCount: snapshot.messageCount, 7});
The memoryBridge handles encoding and retrieval; decay and consolidation run in AgentOS's CognitiveMemoryManager under it. The recall callbacks give the companion agentic access to search its own conversation database. The companion decides when to use them.
Tools she decides to use
Alice calls her tools as function calls during generation, the same way a developer uses APIs. The language model sees the tool descriptions, decides which ones to invoke based on conversation context, receives results, and incorporates them into her response.
| Tool | What it does |
|---|---|
recall_messages | Fetch any message by turn number |
search_conversation | Full-text search across all messages |
conversation_stats | Message counts, attachment counts |
recall_attachments | Find shared images and files |
recall_memories | Query long-term semantic memory |
send_gif | Search and share GIFs from Giphy |
send_selfie | Generate a selfie image of herself |
send_photo | Share stock photos from Pexels/Unsplash |
web_search | Search the web for current information |
generate_image | Create AI illustrations |
analyze_image | Look at any image URL via VLM vision |
Those are the eleven this post is about; wilds.ai's companion code has seven more, among them remember_moment, which writes a memory when the companion decides a moment matters.
The tools are defined as closures that capture request-scoped state. Each tool knows which user it's serving, which companion it belongs to, and what content policy applies. No global state, no shared singletons.
1tools: { 2 analyze_image: { 3 description: 'Look at an image URL to see what it contains.', 4 parameters: { 5 type: 'object', 6 properties: { 7 image_url: { type: 'string' }, 8 }, 9 required: ['image_url'], 10 }, 11 execute: async ({ image_url }) => { 12 const description = await describeImage(image_url); 13 return { description }; 14 }, 15 }, 16 // ... the other tools 17}, 18maxSteps: 12, // model steps per turn, each of which can call tools
When Johnny said "describe what you just sent," Alice didn't match a keyword. She read the conversation, identified that she'd just sent a GIF, extracted the URL from her message metadata, called analyze_image, received a description from the vision model, and wove it into her response. Four steps, one turn, no scripting.
This is what agentic tool use looks like in practice.
Personality that holds across sessions
Alice isn't just a prompt. She has a quantified personality that shapes every response she generates.
AgentOS uses the HEXACO model from personality psychology: six trait dimensions, each scored from 0 to 1. Alice scores high on openness (0.9) and extraversion (0.8), moderate on agreeableness (0.65), and lower on conscientiousness (0.5). These numbers affect her word choices, her willingness to go off-topic, how directly she challenges the user, and how she handles discomfort.
1import { agent } from '@framers/agentos'; 2 3const alice = agent({ 4 name: 'Alice', 5 personality: { 6 honesty: 0.7, 7 emotionality: 0.6, 8 extraversion: 0.8, 9 agreeableness: 0.65, 10 conscientiousness: 0.5, 11 openness: 0.9, 12 }, 13 policyTier: 'standard', 14 // instructions, tools, router ... 15});
The policyTier names the conversation's content tier, one of four: safe, standard, mature, and private-adult. AgentOS routes on it; it doesn't filter. A PolicyAwareRouter sends mature and private-adult conversations to models from its uncensored catalog and leaves safe and standard ones on the default model. When Johnny tried to push Alice into sexual territory, she didn't respond with "I'm sorry, I cannot engage with that content." She responded in character:
Alice: Oh, my! How forward of you. But I'm afraid my adventures are more in the realm of tea parties and philosophical ponderings than such escapades.
Same boundary, completely different experience. The standard tier keeps the conversation on the default model, which declined, and wilds.ai's own content-policy guardrail checks each message and reply against the tier behind it. The personality shapes the refusal. The user doesn't feel policed by a system message. They feel like Alice said no because Alice would say no.
Trust builds over time. wilds.ai builds graduated familiarity on top of the runtime: five stages from stranger to bonded, each gated on both a trust score and the number of memories, and each adding its own instructions to the prompt. The companion starts as a stranger and warms up as trust and memory depth increase. Early conversations are polite and curious. After dozens of exchanges and a shared history of memories, the companion uses inside jokes, references past conversations unprompted, and shows genuine preferences about the user.
Build your own
Five AgentOS pieces cover the runtime side of a companion like Alice:
agent()with inline tools and HEXACO personality- Cognitive memory with Ebbinghaus decay and flashbulb resistance
- Policy-tier model routing that picks the model per content tier without breaking character
VisionPipelinefor image understanding on demand- Media extensions for Giphy (
@framers/agentos-ext-giphy) and Pexels, Unsplash and Pixabay (@framers/agentos-ext-image-search), plusgenerateImagefor illustrations
All TypeScript. All open source. Apache 2.0. The companion layer wilds.ai puts on top (the CompanionOrchestrator, the memory bridge and its recall, the companion's tools, graduated familiarity) is wilds.ai application code, so that part you write yourself.
Prefer markdown? souledAgent() loads a SOUL.md workspace and wires its memory/ wiki as the companion's long-term memory, so its identity and what it remembers are editable, git-versioned files.
npm install @framers/agentos
Start with the 5-minute quickstart. Read the docs. Browse the source on GitHub. Or try it live at wilds.ai, where Alice and dozens of other AI companions are waiting.
AgentOS is built by Frame. See wilds.ai for AI companions and game worlds powered by AgentOS.
