Home Work Sketchbook Backlog About
--:-- CET

Laura Sirvent 2026

Email Instagram Behance

Overthinker (III): Trying to stop it from getting repetitive

06.04.2026

Now that the system basically works, I can already see the next problem: the loop might be too simple.

Right now the structure is this: you check in on the pet, he tells you something about his life, you react to it with a positive, negative, or ignore response, and then he reacts back. That reaction changes his emotional state.

That already works, but if I leave it there it will probably get repetitive very fast. So a big part of the work now is making sure the same structure can still feel different depending on mood. If he is low, maybe he does not really want to tell you much. If he is upset, he can be colder. If he is spiralling, he asks more, pushes more, and needs more reassurance.

Overthinker showing a low mood on screen

Prompting the LLM with all of this in mind is delicate. Finding a free model that is actually useful for this is also part of the problem. More and more I feel that the model itself is not the interesting part. What matters is the framing: what memory it gets, what biography the pet has, what parts of his life he can bring back, and how his voice shifts depending on state.

The backend already has persistent memory. It is a pretty ugly JSON, but it does the job:

{
  "attachment": 6,
  "fragility": 4,
  "resentment": 0,
  "soothed": 31,
  "energy": 96,
  "mood": "calm",
  "pending_initiative": false,
  "utterance_counter": 202
}

And then lower down there are actual dialogue fragments and topic references, for example:

{
  "text": "Overthinker[utt_200]: Pues a mi me paso que el otro dia estuve charlando con un cliente en la tienda y luego me dio la sensación de que me quedé hablando demasiado y lo incomode sin darme cuenta.",
  "source_topic": "futuro_duda"
}

The other thing I am trying to add is initiative. I do not want him to only exist when you poke him. Every now and then he should decide on his own to go “hey” and try to tell you something.

That helps for two reasons. First, it adds surprise. Second, it gives you a small decision: do I listen or do I brush him off? And obviously that should affect him.

Overthinker showing rejection on screen

I am also starting to let bits of the outside world into the device: weather, day, season, and later maybe other information or even news. The tricky part is making sure that does not turn it into an assistant, a weather app, or anything too useful.

One of the prompt rules says this:

Si usas este contexto, hazlo de forma escasa y totalmente filtrada por tu sesgo.
Si el contexto es weather, puedes mencionar temperatura, lluvia o cielo,
pero integrado en tu tono, no como un boletin.
Convierte ese tiempo en sensacion, bajon, pereza, encierro, mal cuerpo o una rayada tuya.

That is probably the balance I am chasing now. I want it to stay somewhere between a narrative device and a tech experiment. I want there to be enough surprise in it that you still feel like giving it what it wants, which is attention and reassurance.

Overthinker (II): Giving it a brain

04.04.2026

This was the point where the project started feeling real.

The firmware runs on the board and I am building that side with PlatformIO. Then there is a backend where the state, logic, memory, and decisions live. And then the LLM sits on top of that, not as the whole brain of the thing, but as a text layer shaped by mood, memory, context, and intent.

I wanted that split from the start because I did not want the pet to just feel like a screen hooked up to a chatbot.

I also started writing the personality down properly so it would stop living only in my head. Right now I have a character canon with things like identity, daily life, social world, psychology, voice, and mood rules. A small part of it looks like this:

"identity": {
    "name": "Overthinker",
    "age_range": "treinta y tantos",
    "life_stage": "adulto funcional pero estancado",
    "core_need": "sentirse validado y percibido como interesante",
    "core_fear": "haber quedado como pesado, raro o fuera de lugar",
    "main_contradiction": "quiere gustar y conectar, pero fuerza la interaccion y genera rechazo",
}

The moods are not just names either. Each one has actual speaking rules:

"spiraling": {
    "speech_pattern": "analiza detalles concretos",
    "interpretation": "sobredimensiona micro senales",
    "focus": "tono, pausas, palabras exactas",
}

I am also building the project in Spanish on purpose. Partly because I think hearing him speak in my own language will make me react to him more instinctively, and partly because it makes me want to keep going with the project.

Visually, he started as more of a blob, very close to the classic tamagotchi look. But pretty quickly I realised that making him human worked much better. It made him easier to read, easier to empathise with, and honestly a bit more awkward in the right way.

At the same time, the hardware limits were shaping the interaction. There are only three buttons: positive, negative, and ignore. That is it. Depending on how you answer, his emotional variables shift.

Version 2 of Overthinker

The OLED has also pushed me into monochrome 1-bit pixel art more than I expected. I am used to having way more tools when I want expression (3D), so working with something this limited is weirdly fun. A pixel is either on or off. That is the whole deal.

I am using u8g2 library for text and sprites rendering, and this is the current talk loop sprite sheet.

Talk loop sprites for Overthinker

Overthinker (I): A virtual pet

02.04.2026

I’ve been in Elda for a few days, staying at my parents’ place, with a bit of unexpected free time. So I gave myself a small challenge: build something using the electronics stuff I already had lying around from a different project that never really worked out.

Vista general de Overthinker montado

The basic idea came from mixing two things I already liked. One was the old tamagotchi logic: a small creature that keeps pulling your attention. The other was a more human thing, which is how often people get stuck talking about themselves, spiralling around their own problems, and using other people for reassurance.

That is where Overthinker came from. Not really a cute pet, and definitely not an assistant. More like a needy little character who keeps making everything about himself.

On the hardware side, I had an ESP32 (a microcontroller board for small electronics and programming projects), a 64x128 OLED screen, a couple of tiny breadboards (those little boards you use to prototype circuits without soldering), wires, and a few push buttons. So the shape of the project was already kind of there: one screen, three buttons, and not much else. The limitations were doing a lot of the design work for me from the start.

ESP32 and protoboard for Overthinker

Later I realised the pet needed sound too, mostly because it had to be able to demand attention in a way that felt a bit more annoying and alive. That is when the piezo speaker (a tiny electronic part that makes sound when you drive it with certain frequencies) entered the story, thanks to a very funny side mission involving my dad and his retired friends trying to find one the day before Easter, with the only electronics shop in town closed.

In the end they found a cheap door alarm from a bazaar and I pulled the piezo out of that.

Door alarm used to get the piezo speaker

I also wanted to use this project to be a bit stricter about process. LLMs make it very easy to build fast and get messy, so I decided to lean into spec-driven development and force myself to define things properly instead of just improvising forever.