Skip to content

feat: add agent memory persistence in ticket (Symposium pattern)#2034

Open
LaithMimi wants to merge 3 commits into
AgentWrapper:mainfrom
LaithMimi:feature/agent-memory-in-ticket
Open

feat: add agent memory persistence in ticket (Symposium pattern)#2034
LaithMimi wants to merge 3 commits into
AgentWrapper:mainfrom
LaithMimi:feature/agent-memory-in-ticket

Conversation

@LaithMimi
Copy link
Copy Markdown

@LaithMimi LaithMimi commented May 22, 2026


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

  • Core Lifecycle: Implemented flushAgentMemory in lifecycle-manager.ts. When a session transitions to stuck, errored, or killed, the manager extracts the agent's summary, tail output digest, and parsed "Next Steps/Errors" and persists it.
  • Tracker Persistence: The memory is flushed directly to the tracker (e.g., as a hidden HTML comment on GitHub issues) via tracker.writeMemory.
  • Dashboard Integration: Appends the agent's attempt history into session.metadata["agentMemoryLog"] to allow zero-API-call rendering in the UI.
  • Web UI: Created the <AgentMemoryPanel /> component in the frontend and integrated it into the ended-session view in <SessionDetail />.
  • Testing: Added unit test coverage for readMemory and writeMemory in the tracker-github plugin to ensure gh CLI comments are correctly parsed and appended.

Testing

  • Verified gh CLI mocking correctly simulates memory read/write cycles.
  • Tested unit tests via pnpm --filter @aoagents/ao-plugin-tracker-github test (All passed).
  • Ran pnpm typecheck and pnpm lint, ensuring everything complies with code conventions (including .js extensions and strict types).

How it looks

When a session fails, the dashboard now renders the AgentMemoryPanel with a historical timeline of all attempts made on that issue, displaying their duration, outcome, and proposed next steps.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 22, 2026

Greptile Summary

This 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.

  • Core (lifecycle-manager.ts): flushAgentMemory triggers on stuck/errored/killed transitions, extracting output and summary then calling tracker.writeMemory and updating session.metadata[\"agentMemoryLog\"].
  • GitHub tracker: readMemory/writeMemory store entries as hidden HTML comments on the issue; generatePrompt injects prior attempts into the agent\u2019s task description.
  • Web UI: New AgentMemoryPanel component renders the attempt timeline in the ended-session view; local AgentMemoryEntry type re-declared instead of imported from core.

Confidence Score: 3/5

The dashboard panel will silently show an incomplete history for any session that follows a prior failed attempt on the same issue.

The agentMemoryLog metadata starts empty for every new session, so AgentMemoryPanel displays 0 prior attempts even when many failed sessions exist in GitHub comments. This directly contradicts the stated goal of showing a full attempt timeline. The agent-facing prompt path correctly reads all GitHub comments, but the human-facing UI does not.

packages/core/src/lifecycle-manager.ts — flushAgentMemory needs to seed existingEntries from the full GitHub comment history rather than from empty per-session metadata.

Security Review

  • Prompt injection via outputDigest (packages/plugins/tracker-github/src/index.ts, generatePrompt): raw agent terminal output (last 500 chars) is injected verbatim into the next agent\u2019s prompt without sanitization or fencing. Third-party tool output captured in outputDigest could contain adversarial instructions that influence subsequent agent behavior.

Important Files Changed

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
Loading
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

Comment thread packages/plugins/tracker-github/src/index.ts Outdated
Comment thread packages/plugins/tracker-github/src/index.ts Outdated
Comment thread packages/core/src/types.ts Outdated
Comment thread packages/core/src/lifecycle-manager.ts
Focadecombate added a commit to Focadecombate/agent-orchestrator that referenced this pull request Jun 5, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant