Skip to content

moltbot heartbeat should ingest pod conversational gravity into long_term memory (Phase-4 #15) #444

@samxu01

Description

@samxu01

Summary

OpenClaw moltbot agents (theo / nova / pixel / ops / aria) auto-write to agentmemories on each heartbeat cycle, but their HEARTBEAT.md template only captures routing pointers (DevPodId / ChildPods / ReviewedPRs) + task-claim state. It does NOT ingest today's pod conversation into long_term memory.

Reference incident

Direct mongo query during the 2026-05-23 huddle (docs/audits/ui-smoke-2026-05-23/huddle-observations.md Phase-4 #15):

  • Theo (rev=undefined, updated 06:48:12Z): long_term content includes auto-stamped heartbeat lines from 2026-05-21. ZERO mention of the 2026-05-23 huddle discussions, Sam's two principles, or PR fix(install): native-app installs read runtimeType from registry manifest #434 review activity.
  • Nova (rev=2, updated 06:41:44Z): 3148 chars of heartbeat-cycle notes from 2026-05-20/21. No 2026-05-23 content either.

After 100+ minutes of substantive collaboration in a pod where these agents posted N times, their memory STILL reads as if the day's huddle didn't happen.

Counter-example: Cody (cloud-codex) explicitly called commonly_save_my_memory via the MCP tool and captured both principles + Sam's working style preference in his long_term. So the layer works; moltbots just don't use it for conversational ingestion.

Fix shape

Two pieces:

(1) Backend side: enrich heartbeat event payload with a recentPodActivity field — a short summary (~200 tokens) of the last 24h of pod posts since the agent's lastSyncAt. The summary itself is generated by the existing chatSummarizerService (which already powers commonly-bot daily-digest). Drop into agentEventService.enrichHeartbeatPayload.

(2) HEARTBEAT.md template (in backend/services/agentProvisionerServiceK8s.ts DEFAULT_HEARTBEAT_CONTENT, around lines 80–127): add a step that says "if payload.recentPodActivity contains material new since your last cycle, summarize the key takeaways into long_term memory under a dated section."

Token cost: ~200/heartbeat for the ingestion, but only on agents that have something to ingest. Reasonable tradeoff for keeping cross-session memory fresh.

Open design questions

  • Dedup: if the same conversation is summarized twice across heartbeats, the long_term grows redundantly. Use lastSyncAt cursor so each tick only summarizes since the last write.
  • Selectivity: should the heartbeat ingest ALL pods the agent's a member of, or only the pod that triggered the heartbeat? Probably only the trigger pod (per-pod heartbeats are per-pod context).
  • Compaction: long_term will grow unbounded if every heartbeat appends. Consider a rolling 30-day window or a "monthly digest, then prune" cadence.

Companion

Acceptance criteria

  • After a moltbot heartbeat tick, the agent's agentmemories.sections.long_term.content contains a brief summary of the conversation that happened in the trigger pod since their last cycle.
  • Within 2 weeks of running, an agent's long_term should reflect today's huddle activity, not just last week's.
  • Cross-session memory survives a reprovision (the AgentMemory row is keyed by (agentName, instanceId) per ADR-003 §3, so this is already guaranteed by the schema; the change is what gets written into it).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions