From 99a2890be2ece4694142a80e0168c588c18daf2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 08:58:01 +0000 Subject: [PATCH] feat: remove LLM extract fallback, require YAML frontmatter Agent output must contain valid YAML frontmatter matching the role schema. If frontmatter parsing fails, the step fails immediately with a clear error instead of falling back to an LLM extraction that can fabricate values. The extract module remains as a public API export but is no longer used in the agent run loop. Breaking change: agents that relied on LLM extraction to produce valid output will now fail. They must output proper frontmatter. --- packages/workflow-agent-kit/src/run.ts | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/workflow-agent-kit/src/run.ts b/packages/workflow-agent-kit/src/run.ts index f6ba1ab..f011fe1 100644 --- a/packages/workflow-agent-kit/src/run.ts +++ b/packages/workflow-agent-kit/src/run.ts @@ -3,10 +3,9 @@ import type { CasRef, StepNodePayload, ThreadId } from "@uncaged/workflow-protoc import { config as loadDotenv } from "dotenv"; import { buildOutputFormatInstruction } from "./build-output-format-instruction.js"; import { buildContextWithMeta } from "./context.js"; -import { extract } from "./extract.js"; import { tryFrontmatterFastPath } from "./frontmatter.js"; import type { AgentStore } from "./storage.js"; -import { getEnvPath, loadWorkflowConfig, resolveStorageRoot } from "./storage.js"; +import { getEnvPath, resolveStorageRoot } from "./storage.js"; import type { AgentContext, AgentOptions, AgentRunResult } from "./types.js"; function fail(message: string): never { @@ -73,24 +72,19 @@ async function runAgent(options: AgentOptions, ctx: AgentContext): Promise>, ): Promise { - const fastPath = await runWithMessage("frontmatter fast path", () => - tryFrontmatterFastPath(rawOutput, outputSchema, ctx.meta.store), - ).catch(() => null); + const fastPath = await tryFrontmatterFastPath(rawOutput, outputSchema, ctx.meta.store); if (fastPath !== null) { return fastPath.outputHash; } - const config = await runWithMessage("failed to load config", () => - loadWorkflowConfig(storageRoot), + fail( + "Agent output does not contain valid YAML frontmatter matching the role schema.\n" + + "The agent must output a YAML frontmatter block (--- delimited) as the first thing in its response.\n" + + `Raw output (first 500 chars): ${rawOutput.slice(0, 500)}`, ); - const extracted = await runWithMessage("extract failed", () => - extract(rawOutput, outputSchema, config), - ); - return extracted.hash; } async function persistStep(options: { @@ -136,12 +130,7 @@ export function createAgent(options: AgentOptions): () => Promise { } const agentResult = await runAgent(options, ctx); - const outputHash = await extractOutput( - agentResult.output, - roleDef.frontmatter, - storageRoot, - ctx, - ); + const outputHash = await extractOutput(agentResult.output, roleDef.frontmatter, ctx); const stepHash = await persistStep({ ctx, outputHash,