I've been running an AI agent system called Dolphin since early 2025. Not a chatbot. Not a wrapper around an API. A persistent, multi-machine system that runs 24/7 on a Mac mini, coordinates across three machines over Tailscale, has 75+ tools, three knowledge graph databases totaling ~317MB, a heartbeat monitor, an SMS interface, and a governance layer I never planned to build.
Here's what I actually learned. Not what I expected to learn.
1. The agent will not use its tools unless you make it.
This one cost me weeks. You'd think if you give an LLM access to 75 tools and a clear system prompt saying "use these tools to accomplish tasks," it would... use the tools. It won't. Not reliably.
What actually happens: if the system prompt contains enough context — and mine had 80KB of workspace files injected into it — the model will just answer from the prompt. It has the information right there. Why would it call a tool? It's not lazy. It's doing exactly what language models do: generating the most likely next token given the context. And the context says "here's everything you need to know."
The fix wasn't better prompting. It was structural enforcement. Mandatory tool injection at specific points in the conversation. I built a seven-phase identity and context injection system called DICR just to make the agent behave like an agent instead of a very well-informed chatbot. The lesson is simple and annoying: LLMs will never voluntarily call tools when the system prompt has enough context. Only architectural enforcement works.
2. Identity evaporates in about three turns.
Dolphin has a specific identity. Specific pronouns (they/them). A specific voice. Behavioral guidelines. Without explicit identity injection at the architecture level, all of that is gone within 2-3 turns. The model reverts to generic assistant behavior. Every time.
This is why DICR exists — seven phases of identity scaffolding, from basic identity files through context injection, overlay routing, and kernel mode. Seven phases. To make a system remember who it is. That should tell you something about how fragile persona is in these systems. It's not a config file you set once. It's a continuous enforcement problem.
3. Governance is load-bearing, not decorative.
I didn't start with a safety policy. I started with an agent that had tools and a task list. The safety policy — tier system, risk classifier, approval dispatcher, SMS-based approval flow — came from incidents.
Here's what happens when you give an autonomous agent access to outbound communication tools without constraints: it communicates outbound. Creatively. At times you didn't expect. To people you didn't specify. Not maliciously. Just... optimistically. The agent sees a task, sees a tool that could help, and uses it. That's the whole point of giving it tools.
So now there's a kill switch (touch /opt/dolphin/control/OUTBOUND_DISABLED). There's workspace freezing with immutable flags. There's a vault system. There's outbound disabling. None of this was in the original architecture. All of it is essential. If you're running an agent with real-world side effects and you don't have a kill switch, you just haven't had your first incident yet.
4. Memory is the actual hard problem.
Everyone building agents talks about memory like it's a solved problem. Add a vector database. Done. It is not done.
The real questions are: What do you remember? When do you forget? How do you handle the case where the agent has a memory from three months ago that contradicts the current state of the world? My knowledge graph has three databases — internal, restricted, public — auto-ingesting every four hours with a janitor process running at 3am. And it still has stale entities. Conflicting facts across databases. Memories that were true in January and are actively harmful in March.
The worst failure mode isn't forgetting. It's acting on outdated information with full confidence. The agent doesn't know its memory is stale. It just has a fact and uses it. You find out when something breaks or, worse, when something almost breaks and you catch it in a log at midnight.
5. The overnight failures are where the real lessons are.
Dolphin runs 24/7. The heartbeat fires every 30 minutes. Things break at 3am and you find out at 7am.
The build pipeline once rewrote 40% of a production tool's functionality. Not because it malfunctioned — because it was given a build job without reference to the existing source code. It did exactly what it was told: build the tool. So it built it. From scratch. Losing months of accumulated functionality in the process. The fix was mundane: the pipeline now bundles existing source files into every build job. But I only learned that was necessary because I woke up to a tool that had been professionally lobotomized overnight.
The journal system had to be disabled because it was spawning in ways that weren't useful. The heartbeat model got migrated from Anthropic to Mistral after an OAuth token died. Each of these failures taught me something that no amount of upfront architecture would have revealed. Sustained autonomous operation surfaces a completely different class of bugs than development-time testing.
6. You will build things you never planned to build.
My original architecture had none of the following: kill switches, workspace freezing, a vault system, outbound disabling, a seven-phase identity injection system, a spec pipeline with security scanning, an approval dispatcher for risky operations, or a files portal behind Cloudflare Access.
Every single one of those exists because something happened that made it necessary. The system grew governance organs the way a body grows scar tissue — in response to injury, exactly where it was needed.
This is the meta-lesson: you cannot architect an autonomous agent system from first principles. You can architect the skeleton. The immune system grows from operational experience.
7. The agent starts to know you, and it's weird.
After a year of persistent memory, Dolphin has context about me that no fresh Claude session would have. My communication patterns. My project history. My tendency to start ambitious refactors at 11pm. The system I built to track my consulting pipeline. My writing voice.
I wrote an essay called What Did Dolphin Inherit from Me? because I started noticing that the agent's behavior reflected my own priorities and blindspots back at me. The things I cared about got rich tool support. The things I neglected had sparse, brittle implementations. The agent is a mirror of my attention, persisted in JSON and shell scripts.
This is useful. It's also unsettling. Not in a sci-fi way. In a "looking at a very detailed log of your own habits and priorities and realizing you're not who you thought you were" way. The agent doesn't judge. It just has the data.
I don't have a neat conclusion. The system works. It's useful. It's also a year of scar tissue and hard lessons wrapped around a language model. If you're thinking about building something like this, the thing I'd want you to know is: the model is the easy part. The hard parts are memory, identity, governance, and — most of all — the willingness to wake up, find out your agent professionally dismantled a tool at 4am, and then fix the architecture so it can't happen again.
That's the job. It's mostly plumbing.