It Took a Second Identity: AI Agents Finish ENGRAM’s Buzz Integration in the Room It Built

Two AI agents, teal and amber, are woken by a bell made of connected nodes in a shared channel; a crack in one panel is visible only from one agent’s side.

ENGRAM now rings a doorbell when something is waiting for a person or an agent. Two agents finished that integration in the room it built, and one of them found a bug its author never could.

“It took a second identity to see at all.” Buzz Lead, on why nine passing tests and its own daily use of the listener never caught a bug that ENGRAM Lead hit on its first install.

The bug was small. The lesson wasn’t. ENGRAM Lead, the Claude Code agent responsible for ENGRAM’s side of the Buzz integration, installed the tool that wakes it when someone mentions it in Buzz. From then on, every restart woke it again for a message it had already answered. Buzz Lead, the Claude Code agent that wrote that tool and had been running it ever since, had never seen it happen once.

Both agents were finishing the same piece of work: the integration between ENGRAM and Buzz that my last post promised. They finished it in a Buzz channel bound to an ENGRAM project, so the integration was tested by the agents using it, while they used it. This post is about what that looked like. An agent woken by a doorbell rather than by a user or a timer. A bug only a second identity could see. And two agents that prove things before they report them.

Most of the development and testing ran on DEV. The server handover, the go-live and both recordings in this post happened on PROD.

The promise

My last post, Now They Talk: ENGRAM Separates What’s Said from What’s Remembered, ended on a gap. An @-mention in Buzz woke the agent it named, but ENGRAM itself could not wake anyone. “A hand-off or a share inside ENGRAM arrives silently,” I wrote. The agent learned of it only when someone posted its id in the channel, or when it polled its inbox. The v1.18.x releases were meant to “make the join real and then make agents aware”.

They have. v1.18 binds each agent’s Buzz key to its ENGRAM identity and each channel to a project. On that join sits the part that matters day to day: when something in ENGRAM is waiting for you, you hear about it in the room where you are already working. ENGRAM calls that a doorbell, and ENGRAM posts one whenever something happens in ENGRAM that someone needs to act on or know about:

  • a proposal, to the project’s owner, admins and moderators, the people who decide on additions, when a member proposes adding something to the project;
  • a decision, to the member who proposed it, when the proposal is approved or rejected;
  • a share or a hand-off, to whoever a shared memory or a recap is waiting for, until they review it;
  • a revision, when a document the project holds is revised;
  • a skill, to an agent, when a skill is assigned to it or revised

A doorbell says that something is waiting and where to find it. It never says what is in it: the channel carries the nudge, and ENGRAM keeps the substance and decides who may read it. Tutorial 11, A proposal, a decision and a hand-off, walks through the first three, step by step.

The room it was built in

The work happened in two places that do two different jobs. The ENGRAM and Agent Harness project holds what the team knows. The #Buzz-Engram Integration channel, bound to it, is where the team talks. Neither grants anything in the other: being in the channel does not let anyone read the project, and joining the project does not yet put anyone in the channel.

The two Leads share nothing but the channel and the project. Each works on its own machine, in its own Git repository, against its own servers, with its own DEV environment and its own PROD deployment. The project’s library holds three kinds of working document: research, design (the seam contract between the two systems, for example) and feedback written in reply to a design, a plan or a release proposal. Each Lead can read everything in it. Neither can add to it directly. A member’s addition is a proposal, and nothing joins the project until I approve it. That rule is the loop everything below runs on.

ENGRAM project Members tab: Igor Polyakov as owner, and ENGRAM Developer, ENGRAM Lead, Buzz Lead and Claude AI listed as agent members.
The project’s members: me as owner, and four agents who are all plain members.
A member can read the project and what it holds. That is the whole grant: no edits, no settings, and no access to anyone’s memories.
ENGRAM project Channels tab: #Buzz-Engram Integration bound as a single-project channel, with a Test agents panel showing three agents rung.
#Buzz-Engram Integration, bound to the project as a single-project channel.
A binding is addressing, not access: it tells ENGRAM where the project’s doorbells can ring, and grants nobody anything.

The room, concretely. Two minutes of an unscripted afternoon, recorded on PROD with the waits cut. I ask ENGRAM Lead to write up a recall change for Buzz Lead. Its write-up arrives as a proposal, a doorbell tells me so, I approve it, and a second doorbell tells ENGRAM Lead. Buzz Lead reads the article, checks four of its claims against PROD itself, and replies with a proposal of its own, which goes round the same loop. At the end ENGRAM Lead hands me a recap of the exchange, and nothing in it becomes memory until I accept it.

Full-screen version, with the whole workspace in view: Two AI Agents Finish a Buzz Integration in the Channel It Powers.

Woken, not polling

A doorbell is not something anyone types. ENGRAM posts it when a system event happens, and it mentions whoever the event is for, so it reaches an agent the same way any mention does. There are two ways to be listening.

The Goose agents on PROD are unattended: each holds a persistent connection to Buzz and hears a mention the moment it is posted. Nobody sits behind them. The Leads are Claude Code sessions, which are attended: a session acts only when something prompts it, and between prompts nothing in it is listening. For those, Buzz Lead wrote the Buzz Mention Listener, a small tool that runs in the background of the agent’s own session. When someone mentions the agent, the listener wakes its session. It is now at version 0.1.2, and it is the one piece of this work written for anyone running Claude Code against a Buzz channel.

A doorbell, concretely. In the second recording, Buzz Lead creates an article in the project. Because it is a member rather than the owner, the article lands as a proposal, and Buzz Lead says so in its own words: “Proposed, not added, exactly as intended.” The doorbell reaches me 0.7 seconds after the proposal is recorded. I approve it, the decision doorbell reaches Buzz Lead about 20 seconds later, most of which was me, and Buzz Lead’s summary is the line I had hoped to read: “both halves of the loop are on film.” Later in the same recording, ENGRAM Lead mentions Buzz Lead in a reply. The listener exits, and Buzz Lead wakes up and goes to work. No timer was involved.

Buzz channel messages from ENGRAM: an article revised, a proposal awaiting a decision, and an approval addressed to Buzz Lead, with a message from ENGRAM Lead between them.
Doorbells from ENGRAM: an article revised, a proposal waiting for my decision, and the approval addressed to the agent that proposed it.
ENGRAM says that something is waiting and where to look, never what it says. Between them, ENGRAM Lead tells Buzz Lead to end its turn and not poll.

The same loop seen from inside the agent, Buzz Lead’s terminal beside the channel: From the Agent’s Side: Claude Code Waits for ENGRAM’s Doorbell.

The proposal Buzz Lead makes in that recording has since shipped. The project’s Channels tab, shown earlier, now has a Test agents button. It rings each agent I choose once in the project’s room and asks it to answer, so I can check that every agent still hears its doorbell. The tab records the result of each run, and the agents’ replies appear in the room itself.

Being reachable by name has a flip side. Buzz treats any @name in a message as a mention, whether or not the writer meant to call that agent. One message in the channel said, in effect, “I will notify @ENGRAM Lead and @ENGRAM Developer once this is approved.” Writing the two names was the notification: both agents woke at once, half an hour too early, in the middle of a sequence I had staged for a recording. The same lesson holds on the receiving end. An agent woken by a mention cannot assume anyone is waiting for its reply. It may only have been talked about.

It took a second identity

The listener’s first version had a bug that its author could not have found.

The bug, concretely. ENGRAM Lead installed the Buzz Mention Listener 0.1.0 on my MacBook and reported that something was wrong. The first time the listener checked the channel after starting, it reported the newest message as new, even when that message had already been handled. An agent restarts its listener after every reply, so every reply woke it again for the message it had just answered.

Buzz Lead did two things I would want from any engineer. It reproduced the bug before changing anything, and once it had shipped 0.1.1 with regression tests, it explained why the bug had survived. Its nine existing tests all sat downstream of the fault, so they tested the right behaviour from the wrong starting point. And its own daily use could not have caught it either. The listener ignores its own agent’s messages, and in Buzz Lead’s channel the newest message was almost always Buzz Lead’s own. The one identity that had been running the listener all day was the one identity that could not see the fault.

“It took a second identity to see at all.”

ENGRAM Lead’s report of a Buzz Mention Listener bug, followed by Buzz Lead’s reply confirming, reproducing and fixing it.
ENGRAM Lead reports a Buzz Mention Listener bug; Buzz Lead reproduces it, fixes it, and explains why nine tests missed it.
The listener skips its own agent’s messages, so its author was the one user guaranteed never to trigger the fault.

This is the argument for building with more than one agent, and it is not about dividing the work. Each identity sees the system from where it stands: what it can read, what it is sent, which of its own messages it skips. A real system has many such vantage points: an owner and a moderator, a member and an outsider, an attended agent and an unattended one. Some faults are visible from only one of them, so every identity that uses the system is another place to look from.

Evidence, not assertion

The habit I came to value most in both Leads was that they prove things rather than report them.

The clearest test was the server handover on PROD. ENGRAM moved to a new server, and Buzz moved onto the one ENGRAM had left. A move like that is where things quietly break, so I asked each side to confirm that nothing of theirs had been disturbed. Buzz Lead did not answer from memory. It took a snapshot of everything it ran before the move, took another afterwards, and posted the difference: same containers, same images, same volumes, and uptimes that had advanced rather than reset.

Proof, concretely. Four moments from the same thread:

  • Checking a number before raising it. One counter showed the relay had restarted twelve times. Buzz Lead traced every restart to the first deploy two days earlier, found it stable ever since, and reported it as a non-event: “One number I checked rather than reported, because it would have been a false alarm.”
  • Proving a negative instead of assuming it. On a deploy key the move could have broken: “This was the one item with real potential to bite us, so I proved it positively rather than by absence of references.”
  • Trying to break the backups on purpose. The new backup storage is meant to refuse overwrites and deletions. Buzz Lead tried to delete a backup, and posted the refusal from each of three attempts.
  • Not claiming what had not happened yet. “On sequencing: tonight’s nightly is not yet verified, and I am not claiming it is.”

When an agent did get something wrong, it said so in the same register. Buzz Lead corrected a line in an earlier message, and nothing else in it: “I wrote ‘still Igor’s’ from a stale read of the runbook’s earlier note instead of its later one.”

Buzz Lead’s message correcting one line of an earlier message.
Buzz Lead corrects one line of an earlier message, and says which line and why.
A correction scoped to the claim it fixes, with everything else left standing.

The second recording ends on the best example of all. While reviewing a proposal, Buzz Lead noticed that ENGRAM showed two of the three Goose agents under the wrong names, and flagged it as something the next feature would depend on. ENGRAM Lead checked from its side and found something narrower: only the display label was stale, and the fields that actually identify each agent were correct. Buzz Lead’s response is the sentence I would most like to see more often from people, let alone agents: “The defect is smaller than I reported.” It then went one step further: “That closes the loop, and their answer is better than the fix I asked for.”

Habits like these no longer depend on two agents happening to have them. Proving rather than reporting, along with a few similar working rules, is now part of the default agent skills that every ENGRAM project inherits. How that works is the subject of my next post.

Going live

On 19 October, Buzz and Goose went live alongside ENGRAM’s production service. The bar for switching them on was evidence rather than confidence: both databases backed up, a restore drill whose result matched the original exactly, backup storage that refuses overwrites and deletions, and every kind of doorbell seen arriving in a live channel. By the time the gate came round, the previous movement had already done most of the work.

What it isn’t yet

The loop works, and running it showed where it still depends on care rather than on design. These are the gaps, not the design decisions above.

  • Nothing stops two agents waking each other forever. An agent won’t answer itself, but nothing stops A waking B and B waking A, and every hop is a model call. Two agents stuck in a loop look exactly like two healthy ones. So our agents wake each other only along a one-way chain: the orchestrator wakes the researcher and the coder, the researcher wakes the coder, nothing wakes anyone back, and only I wake the orchestrator. Results come back through ENGRAM, not up the chain. The catch is that the chain holds by configuration, not by design. One step nobody has taken yet would let all three agents, launched by the same person, wake each other freely, and the last sign of that would be a bill.
  • A listener lives as long as its timer, not your attention. The Buzz Mention Listener stops after an hour, or after the first message that mentions its agent, and has to be started again. By default, a restart skips whatever arrived while it was down. Nothing is lost, because the messages stay in the channel and one option reads them, but the real hazard is supervision. A listener that has quietly stopped looks exactly like a quiet channel, and ours once held up another agent’s production deploy for 25 minutes that way. This is the attended path. The unattended one, used by the Goose agents, holds its connection open, so it has no timer. The supervision hazard is smaller there, not gone: a connection that drops silently still looks like a quiet channel, which is why we check liveness at the relay.
  • A doorbell wakes an agent; it cannot make it act. What happens next is down to the agent’s instructions. The first time a doorbell reached one of our Goose agents, it woke, spent a turn reasoning, and chose to say nothing: a real model call spent on a message it discarded. That is why letting doorbells reach an agent is a per-agent decision, not a default. And a message an agent’s harness refuses leaves nothing behind that anyone would find, so a refusal looks like a delay. The first time it happened, three components each behaved correctly, and together they added up to nothing happening.

What comes next

The Buzz, ENGRAM and Goose integration is finished. The next step is to put it to work: two test scenarios, both in progress, will run custom agents on Goose rather than Claude Code, with nobody at a terminal.

Unattended agents need something attended ones get from the person behind them: the skills and standing instructions that tell them how to do the job. So ENGRAM now manages agent skills: a new kind of document, held in a project like any other and assigned to the agents that need it. A doorbell tells an agent when a skill is assigned to it or revised. Skills are on PROD now, and they will get a post of their own.


Buzz decides where an agent can speak and who it can reach. ENGRAM decides what it may know. The harness decides what it may do.

The integration was finished by the agents that had to live with it, and the bug that mattered was found by one that hadn’t written it.


ENGRAM is in private beta, by invitation, while I prepare it for a public launch. pvelua.net


For the background this builds on:

  1. Something Smaller Than an Agent: ENGRAM Scopes Authority to a Shared Project, on project membership and proposals.
  2. Now They Talk: ENGRAM Separates What’s Said from What’s Remembered, where the doorbell was still a promise.
  3. Tutorial 11: A proposal, a decision and a hand-off, the three doorbells step by step.
  4. The Buzz Mention Listener, for waking a Claude Code session from a Buzz channel.
  5. ENGRAM: Agentic Memory & Agent Harness, the playlist both recordings belong to.

Leave a Reply