diff --git a/packages/workflow-agent-builtin/src/agent.ts b/packages/workflow-agent-builtin/src/agent.ts index b282dbd..a71633c 100644 --- a/packages/workflow-agent-builtin/src/agent.ts +++ b/packages/workflow-agent-builtin/src/agent.ts @@ -17,6 +17,24 @@ import { initSessionDir } from "./session.js"; const log = createLogger({ sink: { kind: "stderr" } }); +const FRONTMATTER_FENCE = "---"; + +/** + * Strip any text before the first `---` fence. + * LLMs sometimes emit preamble text before the frontmatter block. + */ +function stripPreamble(text: string): string { + if (text.startsWith(FRONTMATTER_FENCE)) { + return text; + } + const idx = text.indexOf(`\n${FRONTMATTER_FENCE}\n`); + if (idx !== -1) { + log("6GWRP3QX", `stripped ${idx + 1} chars of preamble before frontmatter`); + return text.slice(idx + 1); + } + return text; +} + type SessionRecord = { sessionId: string; model: string; @@ -74,7 +92,7 @@ async function runBuiltinWithMessages( session.startedAtMs, ); - return { output: loopResult.finalText, detailHash, sessionId: session.sessionId }; + return { output: stripPreamble(loopResult.finalText), detailHash, sessionId: session.sessionId }; } async function runBuiltin(ctx: AgentContext): Promise { diff --git a/packages/workflow-agent-builtin/src/prompt.ts b/packages/workflow-agent-builtin/src/prompt.ts index 5dd3c38..45033e6 100644 --- a/packages/workflow-agent-builtin/src/prompt.ts +++ b/packages/workflow-agent-builtin/src/prompt.ts @@ -66,7 +66,9 @@ export function buildBuiltinMessages(ctx: AgentContext): ChatMessage[] { "You have tools available (read_file, write_file, run_command). " + "Use them to complete your task — read files, run commands, make changes as needed. " + "When you are done, output your final response with the YAML frontmatter block as specified above. " + - "Do NOT output the frontmatter until you have completed all necessary work.", + "Do NOT output the frontmatter until you have completed all necessary work. " + + "CRITICAL: Your final output MUST start with the `---` fence on the very first line — " + + "no preamble text, no explanation before it. The parser requires `---` at position 0.", ); const messages: ChatMessage[] = [{ role: "system", content: systemParts.join("\n") }];