feat: add agent memory persistence in ticket (Symposium pattern)#2034
feat: add agent memory persistence in ticket (Symposium pattern)#2034LaithMimi wants to merge 3 commits into
Conversation
Greptile SummaryThis PR implements the "Symposium pattern" \u2014 persisting agent failure context (what was tried, where it failed, next steps) into GitHub issue comments so subsequent agent attempts can use that history in their prompts, and the dashboard can render a timeline of attempts.
Confidence Score: 3/5The dashboard panel will silently show an incomplete history for any session that follows a prior failed attempt on the same issue. The packages/core/src/lifecycle-manager.ts —
|
| Filename | Overview |
|---|---|
| packages/core/src/lifecycle-manager.ts | Adds flushAgentMemory hooked into session status transitions; the in-memory agentMemoryLog only accumulates within the current session, so the UI panel won’t show prior sessions’ failures. |
| packages/core/src/types.ts | Adds AgentMemoryEntry interface and optional readMemory/writeMemory to Tracker; startedAt/finishedAt typed as Date though JSON round-trips produce strings at runtime. |
| packages/plugins/tracker-github/src/index.ts | Implements readMemory/writeMemory via gh issue comment; raw outputDigest injected verbatim into agent prompts in generatePrompt (prompt injection surface). |
| packages/plugins/tracker-github/test/index.test.ts | Adds readMemory/writeMemory unit tests; vi.hoisted setup uses inline process.platform === "win32" check, violating the repo’s cross-platform convention. |
| packages/web/src/components/AgentMemoryPanel.tsx | New React component rendering agent attempt history; locally re-declares AgentMemoryEntry instead of importing from @aoagents/ao-core, with startedAt/finishedAt as string vs Date in core. |
| packages/web/src/components/SessionDetail.tsx | Integrates AgentMemoryPanel into the ended-session view; layout change wraps SessionEndedSummary in a scrollable flex container — straightforward and safe. |
Sequence Diagram
sequenceDiagram
participant LM as LifecycleManager
participant GHT as tracker-github
participant GH as GitHub API (gh CLI)
participant SM as Session Metadata
participant UI as AgentMemoryPanel
Note over LM: Session transitions to stuck/errored/killed
LM->>GHT: readMemory(issueId, project)
GHT->>GH: gh issue comment list --json body
GH-->>GHT: "[{body: ao-agent-memory comment}]"
GHT-->>LM: AgentMemoryEntry[] (prior attempts)
LM->>LM: build entry
LM->>GHT: writeMemory(issueId, entry, project)
GHT->>GH: gh issue comment --body JSON
LM->>SM: updateSessionMetadata agentMemoryLog
SM-->>UI: current session entries only
Note over LM: Next agent session starts
LM->>GHT: generatePrompt(issueId, project)
GHT->>GH: gh issue comment list --json body
GH-->>GHT: all memory comments (full history)
GHT-->>LM: prompt with PRIOR AGENT ATTEMPTS injected
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 4
packages/core/src/lifecycle-manager.ts:2378-2386
**Panel only ever shows the current session's failures**
`session.metadata["agentMemoryLog"]` is initialized empty at the start of every new session, so `AgentMemoryPanel` will only ever render failures produced within the *current* session's own lifecycle transitions. When a second session is spawned for the same issue, its metadata starts clean — the first session's entries are stored in GitHub comments but are never loaded back into metadata, so the panel shows 0 entries for any fresh session even if 10 prior attempts exist.
The PR description promises "a historical timeline of all attempts made on that issue," but the current implementation only satisfies that for the very first failed session. To show the full history, `flushAgentMemory` should seed `existingEntries` from the GitHub comments (the authoritative store) rather than from the empty local metadata.
### Issue 2 of 4
packages/plugins/tracker-github/test/index.test.ts:18-19
**Inline `process.platform === "win32"` violates the cross-platform rule**
AGENTS.md and CROSS_PLATFORM.md explicitly forbid `process.platform === "win32"` checks outside of `packages/core/src/platform.ts`. Even in test setup, the convention is to use `isWindows()` from `@aoagents/ao-core`. Inside a `vi.hoisted` callback only `require` is available, but `require("@aoagents/ao-core").isWindows()` would satisfy the rule and keep platform branching consistent with how it's mocked elsewhere in the test suite.
### Issue 3 of 4
packages/web/src/components/AgentMemoryPanel.tsx:5-15
**Local `AgentMemoryEntry` re-declaration diverges from the core type**
`packages/core/src/types.ts` exports `AgentMemoryEntry` with `startedAt: Date` and `finishedAt: Date`. This file re-declares the interface with `startedAt: string` / `finishedAt: string`. The string version is technically correct for what arrives after JSON deserialization, but it creates two independent definitions that can silently drift if the core type gains new fields. Import the shared type from `@aoagents/ao-core` and, if needed, define a UI-specific alias with the `string` override.
### Issue 4 of 4
packages/plugins/tracker-github/src/index.ts:290-316
**Raw agent terminal output injected verbatim into the next agent's prompt**
`outputDigest` is the last 500 characters of raw terminal output (stdout/stderr), and it is written into the prompt without any sanitization. If an agent emitted output that resembles a system instruction, the next agent would read it as part of its task context. Because the content originates from the agent's own process output — which could include untrusted third-party tool responses — this is a prompt-injection surface worth demarcating (e.g., wrapping in a code fence so the model treats it as data, not instructions).
Reviews (2): Last reviewed commit: "fix: address code review feedback for ag..." | Re-trigger Greptile
…empt (AgentWrapper#2034) Low-collision local-store variant of verifier-writes-memory: no Tracker interface change. When a review run blocks a PR, the error findings are summarized and stored in the verification DB keyed by issue id (schema v2 adds issue_id + summary, migrated idempotently). On spawn, the session manager looks up getLatestBlockedMemoryForIssue and prompt-builder injects a "Prior Verification Feedback" section so a fresh attempt addresses past blockers instead of repeating them.
Description
This PR implements the Symposium pattern for Agent Orchestrator by persisting "Agent Memory" into issue tickets. When an agent fails, gets stuck, or is killed, its context (what it tried, where it failed, and its proposed next steps) is preserved so subsequent attempts can pick up where it left off, and users can inspect the failure history directly from the dashboard.
Changes Made
flushAgentMemoryinlifecycle-manager.ts. When a session transitions tostuck,errored, orkilled, the manager extracts the agent's summary, tail output digest, and parsed "Next Steps/Errors" and persists it.tracker.writeMemory.session.metadata["agentMemoryLog"]to allow zero-API-call rendering in the UI.<AgentMemoryPanel />component in the frontend and integrated it into the ended-session view in<SessionDetail />.readMemoryandwriteMemoryin thetracker-githubplugin to ensureghCLI comments are correctly parsed and appended.Testing
ghCLI mocking correctly simulates memory read/write cycles.pnpm --filter @aoagents/ao-plugin-tracker-github test(All passed).pnpm typecheckandpnpm lint, ensuring everything complies with code conventions (including.jsextensions and strict types).How it looks
When a session fails, the dashboard now renders the
AgentMemoryPanelwith a historical timeline of all attempts made on that issue, displaying their duration, outcome, and proposed next steps.