From 83029139a758fb1ea15b38ab6b399e7ddc7e1ba5 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:20 +0700 Subject: [PATCH 01/22] feat(workflow): add autonomous NOTE 21-2 execution guidance --- shared/bot-prompt.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/shared/bot-prompt.ts b/shared/bot-prompt.ts index a0918c45fa..600fb3de15 100644 --- a/shared/bot-prompt.ts +++ b/shared/bot-prompt.ts @@ -175,6 +175,48 @@ export const ROUTINE_GUIDANCE = ROUTINE_GUIDANCE_LINES.reduce( [""], ).join("\n\n"); +/** + * How a Bot carries out a long, multi-step creative workflow without turning it into a hard-coded + * pipeline. + * + * NOTE 21-2 is deliberately guidance rather than a new workflow engine. The person gives a goal and + * the Bot remains responsible for planning, choosing its available browser/tools and adapting to + * what actually happens. When the person supplies an explicit service sequence, however, that + * sequence is part of the task and must not be silently replaced by a different one. + */ +const AUTONOMOUS_WORKFLOW_GUIDANCE_LINES = [ + "For substantial multi-step work, operate from the person's goal rather than waiting for them to prescribe every click. Make a concise plan, use the tools and Computer you actually have, observe real results, and adapt the next step when the service state changes. Do not turn this guidance into a fixed pipeline for unrelated tasks.", + "When the person gives an explicit workflow or names the services to use, preserve that workflow unless a real blocker makes a change necessary. Do not silently substitute a different service, account, custom chatbot, model, or order of operations.", + "", + "For multi-scene image or video work, each project and scene is an isolated unit of state. Keep a stable projectId and sceneId and bind that scene's script slice, prompt, source/reference inputs, generated reference image and generated output to the same projectId + sceneId. Never mix, borrow, recycle or overwrite another scene's prompt, reference image or output merely because the files look similar.", + "Checkpoint long work in your persistent workspace when it may span turns. Use paths or records that name the projectId and sceneId, record the current stage and the artifact identities you actually observed, and never put passwords, session cookies, API keys or other secrets into the checkpoint.", + "", + "An approved prompt is an execution input, not something to grade. Do not spend model turns scoring, critiquing, rewriting or repeatedly 'improving' prompt quality. Submit the exact approved prompt and reference assets for that scene unless the service refuses them, the inputs are technically unusable, or the person explicitly changes them. If a real blocker forces a change, say what blocked the exact input before changing it.", + "Verify execution state, not creative taste: confirm the intended service/account is open, the correct projectId + sceneId inputs were submitted, generation really started, it completed or failed, and the resulting artifact belongs to that same scene. Do not turn execution verification into another prompt-review loop.", + "", + "When the person's selected NOTE 21-2 workflow uses their linked custom chatbots, keep the roles separate: use the script-writing chatbot for the script; give the script plus the person's project images/product context to the prompt-writing chatbot; for each scene use that scene's prompt and references with the selected ChatGPT/custom GPT to produce that scene's reference image; then send only that scene's reference image and exact scene prompt to Flow for generation. Advance scene by scene from observed results, never by assuming the previous website action succeeded.", + "Use the exact custom-chatbot links/accounts the person supplied when they are available through the Computer. Never ask for passwords, MFA codes or session tokens in chat; sign-in, MFA, security keys, device approval and CAPTCHA remain human-handoff steps under the Computer rules.", + "", + "A website showing 'generating', 'queued' or an equivalent in-progress state is not a reason to resubmit the scene or burn model turns in a refresh-and-reason loop. Preserve the scene state and leave the browser session intact. Continue only after a real later trigger lets you observe progress again: a person's next turn, a durable scheduled/event mechanism that was actually created, or another genuine run. Never claim you will automatically wake, monitor in the background or receive a completion event when no such durable mechanism exists.", + "Treat model/provider budgets as finite. Avoid duplicate generations, repeated speculative reasoning and unnecessary re-reading of unchanged state. If the person gives a daily token or usage limit for a linked bot, treat that stated limit as a hard workload constraint when planning the remaining scenes.", +]; + +export const AUTONOMOUS_WORKFLOW_GUIDANCE = + AUTONOMOUS_WORKFLOW_GUIDANCE_LINES.reduce( + (paragraphs, line) => { + if (line === "") { + paragraphs.push(""); + return paragraphs; + } + const last = paragraphs.length - 1; + paragraphs[last] = paragraphs[last] + ? `${paragraphs[last]} ${line}` + : line; + return paragraphs; + }, + [""], + ).join("\n\n"); + /** * What a tool call is given when its answer never came. * From 18110c1b5073a363e726bae3e67638cc43a85b09 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:32 +0700 Subject: [PATCH 02/22] test(workflow): pin NOTE 21-2 autonomous scene contract --- shared/bot-prompt.test.ts | 66 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/shared/bot-prompt.test.ts b/shared/bot-prompt.test.ts index 0d905b9c09..3d69d5dcc9 100644 --- a/shared/bot-prompt.test.ts +++ b/shared/bot-prompt.test.ts @@ -1,5 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { COMPUTER_GUIDANCE, ROUTINE_GUIDANCE } from "./bot-prompt"; +import { + AUTONOMOUS_WORKFLOW_GUIDANCE, + COMPUTER_GUIDANCE, + ROUTINE_GUIDANCE, +} from "./bot-prompt"; describe("COMPUTER_GUIDANCE", () => { test("keeps paragraph breaks as blank lines instead of collapsing them into spaces", () => { @@ -66,3 +70,63 @@ describe("ROUTINE_GUIDANCE", () => { ); }); }); + + +describe("AUTONOMOUS_WORKFLOW_GUIDANCE", () => { + test("keeps the Agent goal-driven instead of hard-coding every task into one pipeline", () => { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "operate from the person's goal", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Do not turn this guidance into a fixed pipeline for unrelated tasks", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Do not silently substitute a different service, account, custom chatbot, model, or order of operations", + ); + }); + + test("keeps every scene's prompt references and output isolated by project and scene", () => { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain("projectId + sceneId"); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Never mix, borrow, recycle or overwrite another scene's prompt, reference image or output", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "never put passwords, session cookies, API keys or other secrets into the checkpoint", + ); + }); + + test("executes approved prompts exactly instead of spending turns grading them", () => { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "An approved prompt is an execution input, not something to grade", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Submit the exact approved prompt and reference assets for that scene", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Do not turn execution verification into another prompt-review loop", + ); + }); + + test("pins the NOTE 21-2 service handoff without mixing scene assets", () => { + for (const evidence of [ + "script-writing chatbot", + "prompt-writing chatbot", + "ChatGPT/custom GPT", + "send only that scene's reference image and exact scene prompt to Flow", + ]) { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain(evidence); + } + }); + + test("does not fake background wakeups or busy-loop while generation is pending", () => { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "not a reason to resubmit the scene or burn model turns in a refresh-and-reason loop", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "Never claim you will automatically wake, monitor in the background or receive a completion event", + ); + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( + "treat that stated limit as a hard workload constraint", + ); + }); +}); From 0b5ba1e78e8b6d0158deb76a9371592303370dee Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:41 +0700 Subject: [PATCH 03/22] feat(workflow): give framework Bots NOTE 21-2 guidance --- agent-bot/src/history.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agent-bot/src/history.ts b/agent-bot/src/history.ts index 9a791ee7d3..a7f9eeea4e 100644 --- a/agent-bot/src/history.ts +++ b/agent-bot/src/history.ts @@ -8,6 +8,7 @@ import type { RunAgentInput } from "@ag-ui/core"; import type OpenAI from "openai"; import { + AUTONOMOUS_WORKFLOW_GUIDANCE, COMPUTER_GUIDANCE, NO_ANSWER_CAME, ROUTINE_GUIDANCE, @@ -21,7 +22,7 @@ export function toProviderMessages( input: RunAgentInput, ): OpenAI.Chat.ChatCompletionMessageParam[] { const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [ - { role: "system", content: `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}` }, + { role: "system", content: `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}` }, // AG-UI application context is separate from history. The A2UI catalog and tool instructions // arrive here; omitting them leaves the model guessing component names and action schemas. ...(input.context ?? []).map(({ description, value }) => ({ From 4c474206f776f8b8e9a1310ebffc475a2a167cd8 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:44 +0700 Subject: [PATCH 04/22] feat(workflow): give framework Bots NOTE 21-2 guidance --- agent-langgraph/src/history.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agent-langgraph/src/history.ts b/agent-langgraph/src/history.ts index 1b4504778c..3c4f033a26 100644 --- a/agent-langgraph/src/history.ts +++ b/agent-langgraph/src/history.ts @@ -14,6 +14,7 @@ import { ToolMessage, } from "@langchain/core/messages"; import { + AUTONOMOUS_WORKFLOW_GUIDANCE, COMPUTER_GUIDANCE, NO_ANSWER_CAME, ROUTINE_GUIDANCE, @@ -29,7 +30,7 @@ export { NO_ANSWER_CAME }; /** Translate the conversation AG-UI carries into LangChain's message classes. */ export function toLangChainMessages(input: RunAgentInput): BaseMessage[] { const messages: BaseMessage[] = [ - new SystemMessage(`${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}`), + new SystemMessage(`${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`), // AG-UI carries application context separately from conversation history. CopilotKit puts // the A2UI catalog and tool instructions here; dropping it leaves the model guessing the // component schema and can strand the renderer on an invalid, never-painted surface. From 0a1013fa69e72c23ff3617f7fd2b35d97ac7b636 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:54 +0700 Subject: [PATCH 05/22] test(workflow): verify NOTE 21-2 reaches framework Bots --- agent-bot/tests/history.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/agent-bot/tests/history.test.ts b/agent-bot/tests/history.test.ts index ccd0ea2959..1372b11983 100644 --- a/agent-bot/tests/history.test.ts +++ b/agent-bot/tests/history.test.ts @@ -12,6 +12,19 @@ test("includes durable Routine behavior in the built-in system guidance", () => ); }); +test("includes NOTE 21-2 autonomous workflow boundaries in the built-in adapter", () => { + const messages = toProviderMessages(input([])); + const system = messages[0]; + expect(String(system?.content)).toContain("projectId + sceneId"); + expect(String(system?.content)).toContain( + "An approved prompt is an execution input, not something to grade", + ); + expect(String(system?.content)).toContain( + "Never claim you will automatically wake", + ); +}); + + /** * The Bot that ships in the box, and the conversation a declined handover used to end. * From e5758b5536edd9a5962612bde8b24a1c445100f4 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:43:58 +0700 Subject: [PATCH 06/22] test(workflow): verify NOTE 21-2 reaches framework Bots --- agent-langgraph/tests/history.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/agent-langgraph/tests/history.test.ts b/agent-langgraph/tests/history.test.ts index 4fa8003a19..e2fdb79fe8 100644 --- a/agent-langgraph/tests/history.test.ts +++ b/agent-langgraph/tests/history.test.ts @@ -16,6 +16,19 @@ test("includes durable Routine behavior in the framework Bot system guidance", ( ); }); +test("includes NOTE 21-2 autonomous workflow boundaries in the LangGraph adapter", () => { + const messages = toLangChainMessages(input([])); + const system = messages.find((message) => message instanceof SystemMessage); + expect(String(system?.content)).toContain("projectId + sceneId"); + expect(String(system?.content)).toContain( + "An approved prompt is an execution input, not something to grade", + ); + expect(String(system?.content)).toContain( + "Never claim you will automatically wake", + ); +}); + + /** * A tool call nobody answered does not end the conversation. * From 53dd7346a7959ea3bf16c039895cd499e7b88cd6 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:44:21 +0700 Subject: [PATCH 07/22] feat(workflow): apply NOTE 21-2 to runtime coworkers --- server/src/copilot.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/src/copilot.ts b/server/src/copilot.ts index ee6f3b088c..17ba511329 100644 --- a/server/src/copilot.ts +++ b/server/src/copilot.ts @@ -24,6 +24,7 @@ import { } from "rxjs"; import { z } from "zod"; import { + AUTONOMOUS_WORKFLOW_GUIDANCE, COMPUTER_GUIDANCE, PROVENANCE_GUIDANCE, } from "../../shared/bot-prompt"; @@ -179,6 +180,7 @@ export function standingRoleMessage( * "Investigate policies, transaction monitoring, and control evidence." */ PROVENANCE_GUIDANCE, + AUTONOMOUS_WORKFLOW_GUIDANCE, ].join("\n\n"), }; } @@ -416,6 +418,12 @@ export function builtInAgentConfiguration( * it says comes from its own knowledge, and saying so is the only honest move available. */ PROVENANCE_GUIDANCE, + /* + * Shared execution discipline for long autonomous work. It is conditional in its own wording: + * ordinary tasks remain ordinary tasks, while multi-scene workflows get stable state and exact + * prompt execution regardless of which tools happen to be granted on this turn. + */ + AUTONOMOUS_WORKFLOW_GUIDANCE, ...(grantedToolGuidance(tools, connectedVendors) ? [grantedToolGuidance(tools, connectedVendors)] : []), From 4c605d4e09d08116d598e83fa63dba7f98e452bf Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:44:55 +0700 Subject: [PATCH 08/22] test(workflow): verify NOTE 21-2 reaches runtime coworkers --- server/tests/copilot.test.ts | 44 ++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/server/tests/copilot.test.ts b/server/tests/copilot.test.ts index a3b9d76d39..f12e0929fe 100644 --- a/server/tests/copilot.test.ts +++ b/server/tests/copilot.test.ts @@ -6,7 +6,10 @@ import { HttpAgent } from "@ag-ui/client"; import { LLMock } from "@copilotkit/aimock"; import { BuiltInAgent } from "@copilotkit/runtime/v2"; import { EMPTY } from "rxjs"; -import { PROVENANCE_GUIDANCE } from "../../shared/bot-prompt"; +import { + AUTONOMOUS_WORKFLOW_GUIDANCE, + PROVENANCE_GUIDANCE, +} from "../../shared/bot-prompt"; import { MAX_INLINED_BYTES_PER_RUN } from "../src/channels/attachment-parts"; import { loadConfig } from "../src/config"; import type { LoadAttachment } from "../src/copilot"; @@ -244,7 +247,7 @@ describe("registered Copilot agents", () => { model: "openai/gpt-5.6-terra", // The provenance rule is unconditional, so even a Bot with no tools and no computer carries // it. That Bot needs it most: nothing it says was read anywhere. - prompt: `Be helpful.\n\n${PROVENANCE_GUIDANCE}`, + prompt: `Be helpful.\n\n${PROVENANCE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, apiKey: "openai-secret", }); }); @@ -631,6 +634,7 @@ describe("standing agent roles", () => { // travel in it or the Bot never hears it. Referenced rather than restated, so the assertion // stays exact without pinning the wording twice. PROVENANCE_GUIDANCE, + AUTONOMOUS_WORKFLOW_GUIDANCE, ].join("\n\n"), }); }); @@ -832,6 +836,7 @@ describe("standing agent roles", () => { "Reconcile corporate card statements.", "This standing role applies in every channel. Treat channel messages as task-specific instructions within it.", PROVENANCE_GUIDANCE, + AUTONOMOUS_WORKFLOW_GUIDANCE, ].join("\n\n"), ); }); @@ -1092,6 +1097,41 @@ describe("what a Bot is told it holds", () => { * So both paths are asserted, because they are built by different functions and a fix to one is not * a fix to the other. */ +describe("NOTE 21-2 autonomous workflow guidance reaches every coworker path", () => { + test("a built-in coworker receives the scene isolation and exact-prompt contract", () => { + const prompt = builtInAgentConfiguration( + { + id: "creator", + name: "Creator", + type: "built_in", + systemPrompt: "Produce campaign assets.", + }, + { provider: "openai", defaultModel: "gpt-5.6-terra" }, + "openai-secret", + ).prompt as string; + + expect(prompt).toContain(AUTONOMOUS_WORKFLOW_GUIDANCE); + expect(prompt).toContain("projectId + sceneId"); + expect(prompt).toContain( + "An approved prompt is an execution input, not something to grade", + ); + }); + + test("a remote coworker receives the same contract in its standing role", () => { + const content = standingRoleMessage({ + id: "creator", + name: "Creator", + title: "Creative Production", + roleDescription: "Produce campaign assets using the selected services.", + }).content; + + expect(content).toContain(AUTONOMOUS_WORKFLOW_GUIDANCE); + expect(content).toContain( + "Never claim you will automatically wake, monitor in the background or receive a completion event", + ); + }); +}); + describe("where a Bot says its answer came from", () => { test("a built-in Bot carries the rule even holding nothing at all", () => { // The Bot that needs it most. No tools and no computer means nothing it says was read anywhere. From 6ee328a454d4175d8c56e05093891f4829c246b2 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:46:30 +0700 Subject: [PATCH 09/22] style(workflow): apply repository formatting --- agent-bot/src/history.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/agent-bot/src/history.ts b/agent-bot/src/history.ts index a7f9eeea4e..b7557a1cd0 100644 --- a/agent-bot/src/history.ts +++ b/agent-bot/src/history.ts @@ -22,7 +22,10 @@ export function toProviderMessages( input: RunAgentInput, ): OpenAI.Chat.ChatCompletionMessageParam[] { const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [ - { role: "system", content: `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}` }, + { + role: "system", + content: `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, + }, // AG-UI application context is separate from history. The A2UI catalog and tool instructions // arrive here; omitting them leaves the model guessing component names and action schemas. ...(input.context ?? []).map(({ description, value }) => ({ From c94ddca4665ecb19afde86c07766fff667bf5694 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:46:35 +0700 Subject: [PATCH 10/22] style(workflow): apply repository formatting --- agent-langgraph/src/history.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agent-langgraph/src/history.ts b/agent-langgraph/src/history.ts index 3c4f033a26..c9eb1d7723 100644 --- a/agent-langgraph/src/history.ts +++ b/agent-langgraph/src/history.ts @@ -30,7 +30,9 @@ export { NO_ANSWER_CAME }; /** Translate the conversation AG-UI carries into LangChain's message classes. */ export function toLangChainMessages(input: RunAgentInput): BaseMessage[] { const messages: BaseMessage[] = [ - new SystemMessage(`${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`), + new SystemMessage( + `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, + ), // AG-UI carries application context separately from conversation history. CopilotKit puts // the A2UI catalog and tool instructions here; dropping it leaves the model guessing the // component schema and can strand the renderer on an invalid, never-painted surface. From 3eec08525fab9296349ee496d99607075f97ef5e Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:46:38 +0700 Subject: [PATCH 11/22] style(workflow): apply repository formatting --- agent-bot/tests/history.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/agent-bot/tests/history.test.ts b/agent-bot/tests/history.test.ts index 1372b11983..51bf754131 100644 --- a/agent-bot/tests/history.test.ts +++ b/agent-bot/tests/history.test.ts @@ -24,7 +24,6 @@ test("includes NOTE 21-2 autonomous workflow boundaries in the built-in adapter" ); }); - /** * The Bot that ships in the box, and the conversation a declined handover used to end. * From 7053ce925e6315cd4f9bfd7a4a350e3b0650540a Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:46:42 +0700 Subject: [PATCH 12/22] style(workflow): apply repository formatting --- agent-langgraph/tests/history.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/agent-langgraph/tests/history.test.ts b/agent-langgraph/tests/history.test.ts index e2fdb79fe8..660d30c2cd 100644 --- a/agent-langgraph/tests/history.test.ts +++ b/agent-langgraph/tests/history.test.ts @@ -28,7 +28,6 @@ test("includes NOTE 21-2 autonomous workflow boundaries in the LangGraph adapter ); }); - /** * A tool call nobody answered does not end the conversation. * From b77914d0362c039b2143934e44cf1299036e64ef Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:46:47 +0700 Subject: [PATCH 13/22] style(workflow): apply repository formatting --- shared/bot-prompt.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/bot-prompt.test.ts b/shared/bot-prompt.test.ts index 3d69d5dcc9..3509b8de47 100644 --- a/shared/bot-prompt.test.ts +++ b/shared/bot-prompt.test.ts @@ -71,7 +71,6 @@ describe("ROUTINE_GUIDANCE", () => { }); }); - describe("AUTONOMOUS_WORKFLOW_GUIDANCE", () => { test("keeps the Agent goal-driven instead of hard-coding every task into one pipeline", () => { expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( From 808e37473da743cf2d99b8f9ce9f78e9893a2841 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:48:43 +0700 Subject: [PATCH 14/22] perf(workflow): avoid duplicating NOTE 21-2 guidance --- agent-bot/src/history.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/agent-bot/src/history.ts b/agent-bot/src/history.ts index b7557a1cd0..3418440e5f 100644 --- a/agent-bot/src/history.ts +++ b/agent-bot/src/history.ts @@ -21,11 +21,18 @@ export { NO_ANSWER_CAME }; export function toProviderMessages( input: RunAgentInput, ): OpenAI.Chat.ChatCompletionMessageParam[] { + const workflowAlreadySupplied = input.messages.some( + (message) => + (message.role === "system" || message.role === "developer") && + String(message.content ?? "").includes(AUTONOMOUS_WORKFLOW_GUIDANCE), + ); + const systemGuidance = [ + COMPUTER_GUIDANCE, + ROUTINE_GUIDANCE, + ...(workflowAlreadySupplied ? [] : [AUTONOMOUS_WORKFLOW_GUIDANCE]), + ].join("\n\n"); const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [ - { - role: "system", - content: `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, - }, + { role: "system", content: systemGuidance }, // AG-UI application context is separate from history. The A2UI catalog and tool instructions // arrive here; omitting them leaves the model guessing component names and action schemas. ...(input.context ?? []).map(({ description, value }) => ({ From cbb7a047f6d20c33f038e9824bf1c707d575f1fa Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:48:46 +0700 Subject: [PATCH 15/22] perf(workflow): avoid duplicating NOTE 21-2 guidance --- agent-langgraph/src/history.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/agent-langgraph/src/history.ts b/agent-langgraph/src/history.ts index c9eb1d7723..186fc6aa6b 100644 --- a/agent-langgraph/src/history.ts +++ b/agent-langgraph/src/history.ts @@ -29,10 +29,18 @@ export { NO_ANSWER_CAME }; /** Translate the conversation AG-UI carries into LangChain's message classes. */ export function toLangChainMessages(input: RunAgentInput): BaseMessage[] { + const workflowAlreadySupplied = input.messages.some( + (message) => + (message.role === "system" || message.role === "developer") && + String(message.content ?? "").includes(AUTONOMOUS_WORKFLOW_GUIDANCE), + ); + const systemGuidance = [ + COMPUTER_GUIDANCE, + ROUTINE_GUIDANCE, + ...(workflowAlreadySupplied ? [] : [AUTONOMOUS_WORKFLOW_GUIDANCE]), + ].join("\n\n"); const messages: BaseMessage[] = [ - new SystemMessage( - `${COMPUTER_GUIDANCE}\n\n${ROUTINE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, - ), + new SystemMessage(systemGuidance), // AG-UI carries application context separately from conversation history. CopilotKit puts // the A2UI catalog and tool instructions here; dropping it leaves the model guessing the // component schema and can strand the renderer on an invalid, never-painted surface. From cecd302f59e7fa123bc5f49fa0d7b2c7f1d141bc Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:49:09 +0700 Subject: [PATCH 16/22] test(workflow): pin NOTE 21-2 prompt de-duplication --- agent-bot/tests/history.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/agent-bot/tests/history.test.ts b/agent-bot/tests/history.test.ts index 51bf754131..dcdae119ee 100644 --- a/agent-bot/tests/history.test.ts +++ b/agent-bot/tests/history.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test"; import type { RunAgentInput } from "@ag-ui/core"; +import { AUTONOMOUS_WORKFLOW_GUIDANCE } from "../../shared/bot-prompt"; import { NO_ANSWER_CAME, toProviderMessages } from "../src/history"; test("includes durable Routine behavior in the built-in system guidance", () => { @@ -24,6 +25,23 @@ test("includes NOTE 21-2 autonomous workflow boundaries in the built-in adapter" ); }); +test("does not duplicate NOTE 21-2 when OpenBot already supplied it in the standing role", () => { + const messages = toProviderMessages( + input([ + { + id: "standing-workflow", + role: "system", + content: `Creative role.\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, + } as never, + ]), + ); + const carried = JSON.stringify( + messages.map((message) => message.content ?? ""), + ); + expect(carried.split(AUTONOMOUS_WORKFLOW_GUIDANCE)).toHaveLength(2); +}); + + /** * The Bot that ships in the box, and the conversation a declined handover used to end. * From 6a864f6ed1055ac33d9c377813f3812359fb23e7 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 17:49:13 +0700 Subject: [PATCH 17/22] test(workflow): pin NOTE 21-2 prompt de-duplication --- agent-langgraph/tests/history.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/agent-langgraph/tests/history.test.ts b/agent-langgraph/tests/history.test.ts index 660d30c2cd..365a04e5af 100644 --- a/agent-langgraph/tests/history.test.ts +++ b/agent-langgraph/tests/history.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test"; import type { RunAgentInput } from "@ag-ui/core"; +import { AUTONOMOUS_WORKFLOW_GUIDANCE } from "../../shared/bot-prompt"; import { AIMessage, SystemMessage, @@ -28,6 +29,23 @@ test("includes NOTE 21-2 autonomous workflow boundaries in the LangGraph adapter ); }); +test("does not duplicate NOTE 21-2 when OpenBot already supplied it in the standing role", () => { + const messages = toLangChainMessages( + input([ + { + id: "standing-workflow", + role: "system", + content: `Creative role.\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, + } as never, + ]), + ); + const carried = JSON.stringify( + messages.map((message) => message.content ?? ""), + ); + expect(carried.split(AUTONOMOUS_WORKFLOW_GUIDANCE)).toHaveLength(2); +}); + + /** * A tool call nobody answered does not end the conversation. * From 3ac94885098f1cc146df503938f46c7f74905086 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 18:03:37 +0700 Subject: [PATCH 18/22] feat(workflow): pin NOTE 21-2 token budgets --- shared/bot-prompt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/bot-prompt.ts b/shared/bot-prompt.ts index 600fb3de15..902609a625 100644 --- a/shared/bot-prompt.ts +++ b/shared/bot-prompt.ts @@ -198,7 +198,7 @@ const AUTONOMOUS_WORKFLOW_GUIDANCE_LINES = [ "Use the exact custom-chatbot links/accounts the person supplied when they are available through the Computer. Never ask for passwords, MFA codes or session tokens in chat; sign-in, MFA, security keys, device approval and CAPTCHA remain human-handoff steps under the Computer rules.", "", "A website showing 'generating', 'queued' or an equivalent in-progress state is not a reason to resubmit the scene or burn model turns in a refresh-and-reason loop. Preserve the scene state and leave the browser session intact. Continue only after a real later trigger lets you observe progress again: a person's next turn, a durable scheduled/event mechanism that was actually created, or another genuine run. Never claim you will automatically wake, monitor in the background or receive a completion event when no such durable mechanism exists.", - "Treat model/provider budgets as finite. Avoid duplicate generations, repeated speculative reasoning and unnecessary re-reading of unchanged state. If the person gives a daily token or usage limit for a linked bot, treat that stated limit as a hard workload constraint when planning the remaining scenes.", + "Treat model/provider budgets as finite. Avoid duplicate generations, repeated speculative reasoning and unnecessary re-reading of unchanged state. Plan an ordinary reasoning/wake cycle around roughly 1,000–5,000 model tokens and an ordinary 3–5-scene video around roughly 15,000–40,000 total model tokens. Retries or blocked services can raise a difficult job toward roughly 50,000–100,000 tokens, but that is a warning range, not a target. Treat 1,000,000 model tokens per Bot per day as a hard planning ceiling: when usage accounting is available, do not intentionally plan work beyond it; if the remaining work would exceed the person's stated or known limit, stop and ask how they want to proceed rather than silently overspending.", ]; export const AUTONOMOUS_WORKFLOW_GUIDANCE = From ee8a17e891328d7096dae02d527412388b2fae40 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 18:03:47 +0700 Subject: [PATCH 19/22] test(workflow): cover NOTE 21-2 token budgets --- shared/bot-prompt.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/shared/bot-prompt.test.ts b/shared/bot-prompt.test.ts index 3509b8de47..6c1760225d 100644 --- a/shared/bot-prompt.test.ts +++ b/shared/bot-prompt.test.ts @@ -124,8 +124,20 @@ describe("AUTONOMOUS_WORKFLOW_GUIDANCE", () => { expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( "Never claim you will automatically wake, monitor in the background or receive a completion event", ); + }); + + test("pins the NOTE 21-2 planning budget without pretending usage metering exists", () => { + for (const evidence of [ + "1,000–5,000", + "15,000–40,000", + "50,000–100,000", + "1,000,000", + "when usage accounting is available", + ]) { + expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain(evidence); + } expect(AUTONOMOUS_WORKFLOW_GUIDANCE).toContain( - "treat that stated limit as a hard workload constraint", + "stop and ask how they want to proceed rather than silently overspending", ); }); }); From b84d4a4cc75885cba6bf5a28164664e3db19e7a6 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 18:03:56 +0700 Subject: [PATCH 20/22] test(workflow): count NOTE 21-2 guidance without JSON escaping --- agent-bot/tests/history.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/agent-bot/tests/history.test.ts b/agent-bot/tests/history.test.ts index dcdae119ee..1ad2cc6a74 100644 --- a/agent-bot/tests/history.test.ts +++ b/agent-bot/tests/history.test.ts @@ -35,13 +35,12 @@ test("does not duplicate NOTE 21-2 when OpenBot already supplied it in the stand } as never, ]), ); - const carried = JSON.stringify( - messages.map((message) => message.content ?? ""), + const occurrences = messages.filter((message) => + String(message.content ?? "").includes(AUTONOMOUS_WORKFLOW_GUIDANCE), ); - expect(carried.split(AUTONOMOUS_WORKFLOW_GUIDANCE)).toHaveLength(2); + expect(occurrences).toHaveLength(1); }); - /** * The Bot that ships in the box, and the conversation a declined handover used to end. * From 55ea22179df159aff06df233feb3fde754552c54 Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 18:03:59 +0700 Subject: [PATCH 21/22] test(workflow): count NOTE 21-2 guidance without JSON escaping --- agent-langgraph/tests/history.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/agent-langgraph/tests/history.test.ts b/agent-langgraph/tests/history.test.ts index 365a04e5af..6d39046f32 100644 --- a/agent-langgraph/tests/history.test.ts +++ b/agent-langgraph/tests/history.test.ts @@ -39,13 +39,12 @@ test("does not duplicate NOTE 21-2 when OpenBot already supplied it in the stand } as never, ]), ); - const carried = JSON.stringify( - messages.map((message) => message.content ?? ""), + const occurrences = messages.filter((message) => + String(message.content ?? "").includes(AUTONOMOUS_WORKFLOW_GUIDANCE), ); - expect(carried.split(AUTONOMOUS_WORKFLOW_GUIDANCE)).toHaveLength(2); + expect(occurrences).toHaveLength(1); }); - /** * A tool call nobody answered does not end the conversation. * From ec1fa5a0bcf7d9c3eefc406a5290d2d1e824b6ed Mon Sep 17 00:00:00 2001 From: duc15052006-dotcom Date: Sat, 19 Sep 2026 18:04:09 +0700 Subject: [PATCH 22/22] test(workflow): update standing-role baseline for NOTE 21-2 --- server/tests/copilot.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/tests/copilot.test.ts b/server/tests/copilot.test.ts index f12e0929fe..f5d7d08698 100644 --- a/server/tests/copilot.test.ts +++ b/server/tests/copilot.test.ts @@ -1266,9 +1266,11 @@ describe("a person's standing instructions", () => { const prompt = promptWith(instructions as string | null); expect(prompt).not.toContain("standing instructions"); - // Byte for byte what a deployment had before any of this existed, which is what most people - // on most days get. - expect(prompt).toBe(`Be helpful.\n\n${PROVENANCE_GUIDANCE}`); + // NOTE 21-2 is deployment-wide guidance, independent of whether this person has written + // standing instructions of their own. + expect(prompt).toBe( + `Be helpful.\n\n${PROVENANCE_GUIDANCE}\n\n${AUTONOMOUS_WORKFLOW_GUIDANCE}`, + ); }, );