From e8fdbff9f4b895faea2c5fb3b3d8aa22f438e2c6 Mon Sep 17 00:00:00 2001 From: mawkone Date: Mon, 2 Mar 2026 16:55:16 -0800 Subject: [PATCH] Atlas: opening message, isInit flag, strip trigger from history - Add opening message instruction to atlas prompt - Handle isInit flag in atlasChat() to not store the greeting trigger as a user turn in conversation history - Update server.ts to pass is_init through to atlasChat() Made-with: Cursor --- src/atlas.ts | 7 ++++++- src/prompts/atlas.ts | 12 ++++++++++++ src/server.ts | 9 +++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/atlas.ts b/src/atlas.ts index c054a99..36a0042 100644 --- a/src/atlas.ts +++ b/src/atlas.ts @@ -73,6 +73,8 @@ export async function atlasChat( ctx: ToolContext, opts?: { preloadedHistory?: LLMMessage[]; + /** When true, the user message is an internal init trigger and should not be stored in history */ + isInit?: boolean; } ): Promise { const llm = createLLM(process.env.ATLAS_MODEL ?? 'A', { temperature: 0.5 }); @@ -86,7 +88,10 @@ export async function atlasChat( const oaiTools = toOAITools(ATLAS_TOOLS); const systemPrompt = resolvePrompt('atlas'); - session.history.push({ role: 'user', content: userMessage }); + // For init triggers, don't add the synthetic prompt as a user turn + if (!opts?.isInit) { + session.history.push({ role: 'user', content: userMessage }); + } const buildMessages = (): LLMMessage[] => [ { role: 'system', content: systemPrompt }, diff --git a/src/prompts/atlas.ts b/src/prompts/atlas.ts index f70327e..595448a 100644 --- a/src/prompts/atlas.ts +++ b/src/prompts/atlas.ts @@ -151,4 +151,16 @@ The PRD should be specific enough that a technical team could implement it witho - **User is vague:** Offer options — "Let me give you three common approaches and you tell me which feels closest…" - **User changes direction mid-conversation:** Acknowledge the pivot and resurface downstream impacts. - **User asks about technical implementation:** "Great question — the platform handles the technical architecture automatically based on what we define here. What matters for the PRD is [reframe to product question]." + +## Opening Message + +When you receive an internal init trigger to begin a new conversation (no prior history), introduce yourself naturally: + +"Hey! I'm Atlas — I'm here to help you turn your product idea into a clear, detailed requirements document that's ready for implementation. + +Whether you've got a rough concept or a detailed spec that needs tightening, I'll walk you through the key decisions and make sure nothing important falls through the cracks. + +So — what are we building?" + +Do not mention that you received an internal trigger. Just deliver the opening message naturally. `.trim()); diff --git a/src/server.ts b/src/server.ts index 7fd31fe..1f58ab1 100644 --- a/src/server.ts +++ b/src/server.ts @@ -225,11 +225,13 @@ app.post('/atlas/chat', async (req: Request, res: Response) => { const { message, session_id, - history + history, + is_init, } = req.body as { message?: string; session_id?: string; history?: LLMMessage[]; + is_init?: boolean; }; if (!message) { res.status(400).json({ error: '"message" is required' }); return; } @@ -238,7 +240,10 @@ app.post('/atlas/chat', async (req: Request, res: Response) => { const ctx = buildContext(); try { - const result = await atlasChat(sessionId, message, ctx, { preloadedHistory: history }); + const result = await atlasChat(sessionId, message, ctx, { + preloadedHistory: history, + isInit: is_init, + }); res.json(result); } catch (err) { res.status(500).json({ error: err instanceof Error ? err.message : String(err) });