diff --git a/packages/edge-worker/src/EdgeWorker.ts b/packages/edge-worker/src/EdgeWorker.ts index 3bdd8c55e..f24b8a889 100644 --- a/packages/edge-worker/src/EdgeWorker.ts +++ b/packages/edge-worker/src/EdgeWorker.ts @@ -4744,6 +4744,16 @@ ${taskSection}`; }; } + // Conditionally inject the Graphiti memory MCP server + // https://github.com/getzep/graphiti + const graphitiUrl = process.env.GRAPHITI_MCP_URL?.trim(); + if (graphitiUrl) { + mcpConfig.graphiti = { + type: "http", + url: graphitiUrl, + }; + } + return mcpConfig; } diff --git a/packages/edge-worker/src/PromptBuilder.ts b/packages/edge-worker/src/PromptBuilder.ts index 7f3ef28d5..ad8bd0dcb 100644 --- a/packages/edge-worker/src/PromptBuilder.ts +++ b/packages/edge-worker/src/PromptBuilder.ts @@ -505,6 +505,9 @@ export class PromptBuilder { // Append agent guidance if present prompt += this.formatAgentGuidance(guidance); + // Append memory context instructions if Graphiti is configured + prompt += this.formatMemoryContext(); + if (attachmentManifest) { this.logger.debug( `Adding attachment manifest to label-based prompt, length: ${attachmentManifest.length} characters`, @@ -949,6 +952,9 @@ IMPORTANT: Focus specifically on addressing the new comment above. This is a new // Append agent guidance if present prompt += this.formatAgentGuidance(guidance); + // Append memory context instructions if Graphiti is configured + prompt += this.formatMemoryContext(); + // Append attachment manifest if provided if (attachmentManifest) { this.logger.debug( @@ -1214,6 +1220,23 @@ ${reply.body} return formatted; } + /** + * Format memory context instructions for agents with access to Graphiti. + * Only included when GRAPHITI_MCP_URL is configured. + */ + formatMemoryContext(): string { + if (!process.env.GRAPHITI_MCP_URL?.trim()) { + return ""; + } + return `\n\n +You have access to a team knowledge graph via Graphiti MCP tools. At the start of your work: +1. Use \`search_memory_facts\` with keywords from the issue to recall relevant team patterns, preferences, and past decisions. +2. Apply any recalled context to your work (coding standards, architectural patterns, user preferences). + +During your work, if you discover important patterns or receive corrections, note them for the memory-reflection phase. +`; + } + /** * Extract version tag from template content * @param templateContent The template content to parse @@ -1291,6 +1314,14 @@ ${reply.body} return null; } + // Skip memory-reflection when Graphiti is not configured + if ( + subroutine.name === "memory-reflection" && + !process.env.GRAPHITI_MCP_URL?.trim() + ) { + return "Memory reflection skipped — no knowledge graph configured. Reply: `Memory reflection complete.`"; + } + const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const subroutinePromptPath = join( diff --git a/packages/edge-worker/src/RunnerSelectionService.ts b/packages/edge-worker/src/RunnerSelectionService.ts index 81901ced1..33824ef95 100644 --- a/packages/edge-worker/src/RunnerSelectionService.ts +++ b/packages/edge-worker/src/RunnerSelectionService.ts @@ -412,6 +412,9 @@ export class RunnerSelectionService { if (process.env.SLACK_BOT_TOKEN?.trim()) { tools.push("mcp__slack"); } + if (process.env.GRAPHITI_MCP_URL?.trim()) { + tools.push("mcp__graphiti"); + } return tools; } diff --git a/packages/edge-worker/src/procedures/registry.ts b/packages/edge-worker/src/procedures/registry.ts index 275bd32e9..3f227756c 100644 --- a/packages/edge-worker/src/procedures/registry.ts +++ b/packages/edge-worker/src/procedures/registry.ts @@ -129,6 +129,14 @@ export const SUBROUTINES = { suppressThoughtPosting: true, disallowAllTools: true, }, + memoryReflection: { + name: "memory-reflection", + promptPath: "subroutines/memory-reflection.md", + singleTurn: true, + description: "Reflecting on session and storing learnings to memory", + skipLinearPost: true, + suppressThoughtPosting: true, + }, } as const; /** @@ -166,6 +174,7 @@ export const PROCEDURES: Record = { SUBROUTINES.gitCommit, SUBROUTINES.ghPr, SUBROUTINES.conciseSummary, + SUBROUTINES.memoryReflection, ], }, @@ -181,6 +190,7 @@ export const PROCEDURES: Record = { SUBROUTINES.gitCommit, SUBROUTINES.ghPr, SUBROUTINES.conciseSummary, + SUBROUTINES.memoryReflection, ], }, diff --git a/packages/edge-worker/src/prompts/subroutines/memory-reflection.md b/packages/edge-worker/src/prompts/subroutines/memory-reflection.md new file mode 100644 index 000000000..ab223899e --- /dev/null +++ b/packages/edge-worker/src/prompts/subroutines/memory-reflection.md @@ -0,0 +1,26 @@ +# Memory Reflection Phase + +Review the work completed in this session and store important learnings to the team knowledge graph. + +## What to Store + +Use `add_memory` for each distinct learning. Focus on: + +- **Coding patterns**: conventions, file organization, naming standards observed in the codebase +- **User preferences**: explicit corrections or preferences expressed by the assignee +- **Architectural decisions**: technology choices, design patterns, dependency decisions +- **Business context**: domain terms, workflow rules, team processes + +## Guidelines + +- Only store facts that would be useful in future sessions +- Be specific — "uses Tailwind v4" is better than "uses CSS framework" +- Include the entity involved — "cyrus-hosted uses barrel exports in components/" not just "uses barrel exports" +- Do NOT store session-specific details (issue numbers, branch names, PR URLs) +- Do NOT store information that's already in the codebase's README or CLAUDE.md + +## Constraints + +- You have exactly 1 turn +- Store 0-5 learnings (0 is fine if nothing new was learned) +- Complete with: `Memory reflection complete.`