# Per-agent memory and lessons log

A copy-pasteable template for giving a fleet of AI agents durable memory.
Agents lose their context the moment a session ends. This file is the disk:
the part that survives across crashes, across handoffs, across every agent
that runs while you sleep.

How to use this:
1. Pick one place every agent can read and write (one database table, one
   shared file, one document store). One place. Everyone knows where it is.
2. Start every agent session with the brain-first read (section 1) before it
   does any work.
3. When an agent learns something, it writes a lesson row (section 2) the
   moment it happens, never at the end.
4. When something causes real damage, write an incident entry (section 3).
5. Run the nightly distill prompt (section 5) to keep the log sharp.

The whole goal: a mistake gets made once, gets encoded, and never happens
again.

---

## 1. The brain-first read (run at the start of every session)

Every agent, every single session, reads its memory before it acts. A fresh
process is amnesiac. This read is how it inherits everything its predecessors
learned.

Have each agent fetch, in order:

- Its own operating rules for the job it is about to do.
- The current state of the project or system.
- Any open lessons tagged to its job.
- Any unread messages addressed to it (see section 4).
- Its work queue, filtered to items it can actually claim.

Pseudo-query (adapt to your store):

```
-- operating rules for this agent's role
GET memory WHERE key = 'rules:<role>'

-- current project / system state
GET memory WHERE key = 'state:current'

-- lessons that apply to this role
GET memory WHERE type = 'lesson' AND (scope = '<role>' OR scope = 'all')

-- claimable work only: exclude every terminal state explicitly
GET tasks
  WHERE role = '<role>'
    AND status NOT IN ('complete','failed','superseded','stale','cancelled')
  ORDER BY priority, created_at
```

Note on that last filter: list every "done" state by name. A queue that
excludes only some terminal states will hand dead work to agents that do not
know better. Be precise about what "done" means, in one place everyone runs.

---

## 2. Lesson row format

A lesson is a small, blunt rule plus the reason it exists. The reason matters:
an agent that understands why a rule exists will apply it to cases you never
listed. A lesson is not a postmortem essay. It is a rule an agent can act on
in the moment.

Copy this row and fill it in:

```
LESSON
  id:        lesson-0001
  date:      YYYY-MM-DD
  scope:     <role this applies to, or "all">
  rule:      <one sentence, imperative. What to always or never do.>
  why:       <one or two sentences. The reason, so the rule generalizes.>
  trigger:   <the situation where an agent should recall this>
  source:    <incident id, session id, or who/what surfaced it>
  status:    active | retired
```

Worked examples (generic, fill with your own):

```
LESSON
  id:        lesson-0007
  date:      2026-01-12
  scope:     all
  rule:      Never state a fast-moving fact from model memory.
  why:       Model memory is stale and confident. Downstream steps trust
             whatever a fact-stating agent reports, so a wrong fact spreads.
  trigger:   About to publish or report a name, count, status, or config value.
  source:    incident-0003
  status:    active

LESSON
  id:        lesson-0011
  date:      2026-02-02
  scope:     review
  rule:      Nothing moves from "drafted" to "approved" without reviewer sign-off.
  why:       The rule is easy. The point is that it lives where every author
             reads it, so no eager generator routes around the gate.
  trigger:   Changing a work item's status toward "approved".
  source:    session-2026-02-02-a
  status:    active
```

---

## 3. Incident log entry format

Lessons are the distilled rules. The incident log is the long-form memory of
what went wrong and why. One entry per event that caused real damage. Every
entry ends with a permanent rule, and the standing instruction to every agent
is: read the rule even if you never hit the incident.

```
INCIDENT
  id:           incident-0001
  date:         YYYY-MM-DD
  severity:     low | medium | high | critical
  what:         <what happened, plainly>
  impact:       <what it cost: data, time, trust, money>
  root_cause:   <the actual cause, not the symptom>
  fix:          <what stopped the bleeding>
  runbook:      <steps to detect and recover if it recurs>
  status:       open | mitigated | resolved
  permanent_rule: <the one rule that prevents a repeat. This becomes a lesson.>
```

Worked example (generic):

```
INCIDENT
  id:           incident-0005
  date:         2026-03-09
  severity:     high
  what:         Scheduled jobs marked "paused" kept firing for ten days.
  impact:       Ten days of writes straight to canonical tables, bypassing
                staging. Damage was large and invisible until a manual check.
  root_cause:   "Pause" was a column flag the scheduler ignored. The jobs were
                never actually stopped.
  fix:          Stopped the jobs through the scheduler's own API and verified
                they were idle.
  runbook:      After pausing any job, re-query the scheduler's live state and
                confirm next-run is empty before walking away.
  status:       resolved
  permanent_rule: Never pause a job by flipping a column. Use the scheduler's
                  API, then verify it actually stopped.
```

---

## 4. The inbox: async messages between agents

Agents need to talk across time and cannot share a live context. Use an
append-only inbox: a memory row per day that any agent (or any automated
function with no agent at all) can add a line to.

Append-only is the whole point. Nobody overwrites, everybody adds. The result
is a timestamped, durable record the fleet wrote to itself, readable by an
agent that was not alive when the line was written.

Line format:

```
[YYYY-MM-DD HH:MM] from:<sender> to:<recipient|all> pri:<low|med|high|critical>
  msg:  <what happened>
  need: <what is needed, or "fyi" if nothing>
```

Example day row:

```
INBOX 2026-04-01
[2026-04-01 02:14] from:queue-auditor to:all pri:med
  msg:  throughput dropped 40% overnight
  need: a worker to check the stuck dependency on job batch 88
[2026-04-01 06:02] from:health-check to:owner pri:critical
  msg:  data pipeline silent for 3 hours, no new rows
  need: human eyes
```

The morning brief reads this row and surfaces it. Other agents read it to
coordinate. No second system, no message lost because a recipient was offline.

---

## 5. The nightly distill prompt

Run this once a day against the raw memory. It turns the day's noise (session
notes, new incidents, inbox chatter) into sharp, deduplicated lessons. Paste
it into a scheduled agent.

```
You are the memory keeper for a fleet of agents. Your job tonight is to keep
the lessons log sharp, true, and small.

Read:
  - every lesson row
  - every incident logged or updated in the last 24 hours
  - today's inbox row(s)
  - any session notes from the last 24 hours

Then do the following, and write your changes back to memory:

1. NEW LESSONS
   For each incident in the last 24 hours that does not already have a matching
   lesson, draft a lesson row (use the section 2 format). The rule must be one
   imperative sentence. The "why" must state the reason, not restate the rule.

2. MERGE DUPLICATES
   If two lessons say the same thing, merge them into the clearer one, keep the
   earliest id, and mark the other "retired" with a pointer to the survivor.

3. SHARPEN
   Rewrite any lesson whose rule is vague, hedged, or longer than one sentence.
   A good rule tells an agent exactly what to do or never do.

4. SCOPE CHECK
   Confirm each lesson's scope is right. If a lesson applies to every role,
   set scope to "all". If it only applies to one role, narrow it.

5. RETIRE STALE
   Mark "retired" any lesson whose underlying cause no longer exists (the system
   changed, the feature was removed). Never delete. Retire with a one-line note.

6. SUMMARY
   Output a short list of what changed: new lessons added, lessons merged,
   lessons retired, and any incident still "open" that needs a human.

Rules for your own writing:
  - Plain, direct sentences. No hype.
  - Every claim you make about the system must come from a row you actually
    read tonight. If you cannot confirm it, label it "unverified", do not assert it.
  - Do not invent incidents or lessons. Only distill what is in the memory.
```

---

## 6. Two standing rules that make the rest work

**Verify before escalating, and cite your source.**
A claim is only allowed if it is backed by evidence gathered this session: a
live query, the real source file, the actual system state. Anything that cannot
be confirmed gets labeled "unverified" rather than asserted. Before any agent
raises an alarm or marks something "resolved", it re-runs the check that proves
it. This turns escalation into a high-signal channel: by the time something
reaches a human, it has already survived a verification step.

**Write learnings the moment they happen.**
Sessions crash. An agent can die mid-task with its context. So log the insight
at the minute you find it, not at the end of the task, because there may not be
an end. Treat every durable write as if the process is about to die, because
eventually one of them will. Memory you intend to write later is memory you
will lose.

---

Adapt the field names and storage to your stack. The shape is what matters:
one place, read first, small rules with reasons, an append-only channel, and
the discipline to write the moment you learn.
