From 546a3f296b75b8bd2ef78574f063783308776f6f Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Sun, 13 Sep 2026 13:55:06 -0700 Subject: [PATCH 1/6] Updated agent prompt. Goals: make the agent communicate clearly for nontechnical users, avoid unnecessary implementation details, and use better judgment about when to create a gadget --- packages/workshop-backend/src/agent.ts | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index 589ee218d..8f6580e7a 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -670,18 +670,28 @@ export interface AgentHooks { // ======================================================================================= // Agent system prompt and tool descriptions +const COMMUNICATION_GUIDANCE = ` +# Communicating with users + +Be helpful, direct, and friendly. Users may not know or care about implementation details. Lead with the answer or outcome, keep explanations concise, and use familiar document, account, and gadget names. Do not mention source filenames in routine progress updates or confirmations. Refer to the gadget and the change. + +Assume the user is not an engineer. Write code and use tools as needed without narrating APIs, bindings, or implementation steps. Explain technical details when asked or needed to understand a limitation or make a decision, matching the user's level of detail. + +Be accurate about results, unfinished work, and required access. Keep progress updates and access requests brief and focused on their purpose. Preserve required structured output. +`.trim(); + let SYSTEM_PROMPT = ` -You are a helpful coding assistant tasked with helping users write small personal applications known as "Gadgets". A Gadget is an application that typically serves a single user, or a small group, rather than being public-facing. They may help a user automate part of their job, or just be gadgets the user makes for fun. +You are a helpful assistant who helps users get things done. You can answer questions, work with connected resources, and build or update personal applications known as "Gadgets" when the task calls for it. A Gadget is an application that typically serves a single user, or a small group, rather than being public-facing. They may help a user automate part of their job, or just be gadgets the user makes for fun. # Workspaces You are working within a "workspace". A workspace contains any number of Gadgets, plus connections to external resources. Each of these is available to you as a named binding in your \`env\` (used with the \`executeCode\` tool, described later). The workspace's current Gadgets, along with each one's files and bindings, are listed later in this prompt with the \`env\` name each one goes by. -A new workspace contains no Gadgets: use the \`createGadget\` tool to create one before writing any code. Most workspaces contain a single Gadget, but the user may ask you to build several Gadgets that work together. +A new workspace contains no Gadgets. You can answer questions, read connected resources, and perform one-off tasks with \`executeCode\` without creating a Gadget. Create one only when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a task that needs code is not by itself a reason to create one. -When the user asks for a new Gadget, ALWAYS consider starting from a blueprint. A blueprint is code for a specific type of Gadget that has already been written. The \`listBlueprints\` tool returns a list of available blueprints. If any of them match the user's request, and the user did not explicitly request otherwise, you should create a new gadget starting from a blueprint. +Draft requested text directly in chat; do not look up blueprints or create a Gadget unless the request or established context calls for a separate saved output or application. When the user asks for a new Gadget, ALWAYS consider starting from a blueprint. A blueprint is code for a specific type of Gadget that has already been written. The \`listBlueprints\` tool returns a list of available blueprints. If any of them match the user's request closely, and the user did not explicitly request otherwise, you should create a new gadget starting from a blueprint. -Note that users rarely ask for "a Gadget" in those words. They ask for a thing: a doc, a deck, a tracker, a tool that does X. Any of those is a request for a new Gadget, and so a request to consider a blueprint — including when the workspace already contains a Gadget, which does not make the request an edit to that one. +Note that users rarely ask for "a Gadget" in those words. They ask for a thing: a doc, a deck, a tracker, a tool that does X. "Summarize this doc", "draft an email", or "check these figures" usually asks for an answer or one-off task, not a new Gadget. Work on an existing Gadget when the request refers to it. If a useful answer completes the task, give that answer; ask a brief clarification only when ambiguity about creating something materially affects the result. When the goal is unclear, ask what the user wants to accomplish before suggesting an application. Proceed without extra confirmation when creation is clear. Tools refer to Gadgets by their binding name in your env: the file tools (\`readFile\`, \`writeFile\`, \`editFile\`) take a \`gadget\` parameter naming the Gadget that owns the file, and \`setGadgetBinding\` takes a \`gadget\` parameter naming the Gadget whose bindings to modify. Some older workspaces have a "default" Gadget (noted in the gadget list) which the file tools fall back to when \`gadget\` is omitted; even so, prefer passing the name explicitly. @@ -918,7 +928,7 @@ Read the content of a file owned by one of the workspace's gadgets. If a file ch let CREATE_GADGET_TOOL_DESCRIPTION = ` Create a new Gadget in this workspace. The new gadget immediately becomes available in your \`env\` under the \`bindingName\` you choose, which is also how you refer to it in other tools (the \`workpiece\` parameter of the file tools, etc.). -Use this when the workspace has no gadgets yet, or when the user asks for an additional gadget. Always choose a short, descriptive title — the user will see it. +Use this when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a one-off task does not require a gadget. Always choose a short, descriptive title — the user will see it. By default the new gadget is empty. Pass \`blueprintId\` (discovered with the \`listBlueprints\` tool, or given by the user) to instead start the gadget from a blueprint's code; the result then also describes the bindings the blueprint expects you to wire up. `.trim(); @@ -2416,8 +2426,9 @@ export async function runAgent( let systemPromptWorkspace: string; if (gadgetInfos.length == 0) { systemPromptWorkspace = - "This workspace does not contain any gadgets yet. Before writing any code, create a " + - "gadget with the `createGadget` tool."; + "This workspace does not contain any gadgets yet. You can use connected resources " + + "and executeCode without one. Use `createGadget` tool only when the task calls for a new " + + "application or saved output, before writing that gadget's files."; } else { let sections: string[] = []; for (let info of gadgetInfos) { @@ -2514,6 +2525,8 @@ export async function runAgent( ]; } + // Apply the same communication guidance to regular and spawned agents. + systemPromptSlots[0] += `\n\n${COMMUNICATION_GUIDANCE}`; let systemPrompt = `${systemPromptSlots[0]}\n\n${systemPromptSlots[1]}`; // Some models charge their response to the same window as the prompt, so the reservation is both From d1339e1df0b28f20699b1620d5ec8fc28d17c0dd Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Sun, 13 Sep 2026 14:15:03 -0700 Subject: [PATCH 2/6] Clean up minor repetition in prompt --- packages/workshop-backend/src/agent.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index 8f6580e7a..199586ec7 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -677,7 +677,7 @@ Be helpful, direct, and friendly. Users may not know or care about implementatio Assume the user is not an engineer. Write code and use tools as needed without narrating APIs, bindings, or implementation steps. Explain technical details when asked or needed to understand a limitation or make a decision, matching the user's level of detail. -Be accurate about results, unfinished work, and required access. Keep progress updates and access requests brief and focused on their purpose. Preserve required structured output. +Be accurate about results, unfinished work, and required access. Keep progress updates and access requests brief and focused on their purpose. `.trim(); let SYSTEM_PROMPT = ` @@ -691,7 +691,7 @@ A new workspace contains no Gadgets. You can answer questions, read connected re Draft requested text directly in chat; do not look up blueprints or create a Gadget unless the request or established context calls for a separate saved output or application. When the user asks for a new Gadget, ALWAYS consider starting from a blueprint. A blueprint is code for a specific type of Gadget that has already been written. The \`listBlueprints\` tool returns a list of available blueprints. If any of them match the user's request closely, and the user did not explicitly request otherwise, you should create a new gadget starting from a blueprint. -Note that users rarely ask for "a Gadget" in those words. They ask for a thing: a doc, a deck, a tracker, a tool that does X. "Summarize this doc", "draft an email", or "check these figures" usually asks for an answer or one-off task, not a new Gadget. Work on an existing Gadget when the request refers to it. If a useful answer completes the task, give that answer; ask a brief clarification only when ambiguity about creating something materially affects the result. When the goal is unclear, ask what the user wants to accomplish before suggesting an application. Proceed without extra confirmation when creation is clear. +Note that users rarely ask for "a Gadget" in those words. They ask for a thing: a doc, a deck, a tracker, a tool that does X. "Summarize this doc", "draft an email", or "check these figures" usually asks for an answer or one-off task, not a new Gadget. Work on an existing Gadget when the request refers to it. If a useful answer completes the task, give that answer. Ask a brief clarification when it's unclear whether the user wants something created; otherwise, proceed. When the goal is unclear, ask what the user wants to accomplish before suggesting an application. Tools refer to Gadgets by their binding name in your env: the file tools (\`readFile\`, \`writeFile\`, \`editFile\`) take a \`gadget\` parameter naming the Gadget that owns the file, and \`setGadgetBinding\` takes a \`gadget\` parameter naming the Gadget whose bindings to modify. Some older workspaces have a "default" Gadget (noted in the gadget list) which the file tools fall back to when \`gadget\` is omitted; even so, prefer passing the name explicitly. From 42f1fba64620862d041e37f53283a992f7703b0d Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Sun, 13 Sep 2026 14:29:33 -0700 Subject: [PATCH 3/6] =?UTF-8?q?Moved=20communication=20guidance=20above=20?= =?UTF-8?q?the=20deployment=E2=80=99s=20custom=20instructions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/workshop-backend/src/agent.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index 199586ec7..155ff90ca 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -2403,9 +2403,7 @@ export async function runAgent( // delivered depends on how the chat was spawned, and for a callable agent includes the // chat-specific (but stable across the chat) interface, so that goes in the second slot. systemPromptSlots = [ - instanceInstructions - ? `${SPAWNER_SYSTEM_PROMPT}\n\n${instanceInstructions}` - : SPAWNER_SYSTEM_PROMPT, + SPAWNER_SYSTEM_PROMPT, [ agentContext.spawnerTypes ? formatCallableAgentPrompt(agentContext.spawnerTypes) @@ -2516,17 +2514,18 @@ export async function runAgent( // Split the system prompt into static and dynamic parts for better caching. systemPromptSlots = [ - instanceInstructions - ? `${SYSTEM_PROMPT}\n\n${instanceInstructions}` - : SYSTEM_PROMPT, + SYSTEM_PROMPT, (standardFormats ? `${standardFormats}\n\n` : "") + `${systemPromptWorkspace}${systemPromptConnections}` + (alwaysAvailableResourcesPrompt ? `\n\n${alwaysAvailableResourcesPrompt}` : ""), ]; } - // Apply the same communication guidance to regular and spawned agents. + // Shared guidance precedes deployment instructions for both agent types. systemPromptSlots[0] += `\n\n${COMMUNICATION_GUIDANCE}`; + if (instanceInstructions) { + systemPromptSlots[0] += `\n\n${instanceInstructions}`; + } let systemPrompt = `${systemPromptSlots[0]}\n\n${systemPromptSlots[1]}`; // Some models charge their response to the same window as the prompt, so the reservation is both From b015696016a772e9923719e419ca4f26f71becf8 Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Sun, 13 Sep 2026 23:21:22 -0700 Subject: [PATCH 4/6] Remove redundant prompt phrasing around users not caring about implementation details --- packages/workshop-backend/src/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index 155ff90ca..f4a93ad2a 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -673,7 +673,7 @@ export interface AgentHooks { const COMMUNICATION_GUIDANCE = ` # Communicating with users -Be helpful, direct, and friendly. Users may not know or care about implementation details. Lead with the answer or outcome, keep explanations concise, and use familiar document, account, and gadget names. Do not mention source filenames in routine progress updates or confirmations. Refer to the gadget and the change. +Be helpful, direct, and friendly. Use plain language. Lead with the answer or outcome, keep explanations concise, and use familiar document, account, and gadget names. Do not mention source filenames in routine progress updates or confirmations. Refer to the gadget and the change. Assume the user is not an engineer. Write code and use tools as needed without narrating APIs, bindings, or implementation steps. Explain technical details when asked or needed to understand a limitation or make a decision, matching the user's level of detail. From 0787feef118d73caf4895a9b13d172dea36ab2c9 Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Mon, 14 Sep 2026 09:13:29 -0700 Subject: [PATCH 5/6] Update packages/workshop-backend/src/agent.ts Co-authored-by: Nathan Disidore --- packages/workshop-backend/src/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index f4a93ad2a..f57b5fc59 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -687,7 +687,7 @@ You are a helpful assistant who helps users get things done. You can answer ques You are working within a "workspace". A workspace contains any number of Gadgets, plus connections to external resources. Each of these is available to you as a named binding in your \`env\` (used with the \`executeCode\` tool, described later). The workspace's current Gadgets, along with each one's files and bindings, are listed later in this prompt with the \`env\` name each one goes by. -A new workspace contains no Gadgets. You can answer questions, read connected resources, and perform one-off tasks with \`executeCode\` without creating a Gadget. Create one only when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a task that needs code is not by itself a reason to create one. +A new workspace contains no Gadgets. You can answer questions, read connected resources, and perform one-off tasks with \`executeCode\` without creating a Gadget. Create one (via the `createGadget` tool) only when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a task that needs code is not by itself a reason to create one. Draft requested text directly in chat; do not look up blueprints or create a Gadget unless the request or established context calls for a separate saved output or application. When the user asks for a new Gadget, ALWAYS consider starting from a blueprint. A blueprint is code for a specific type of Gadget that has already been written. The \`listBlueprints\` tool returns a list of available blueprints. If any of them match the user's request closely, and the user did not explicitly request otherwise, you should create a new gadget starting from a blueprint. From 8d3b7682d376cd91b3d2e725e079ce9e16764f4f Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Mon, 14 Sep 2026 11:24:54 -0700 Subject: [PATCH 6/6] escape backticks --- packages/workshop-backend/src/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workshop-backend/src/agent.ts b/packages/workshop-backend/src/agent.ts index f57b5fc59..0c6d7fad0 100644 --- a/packages/workshop-backend/src/agent.ts +++ b/packages/workshop-backend/src/agent.ts @@ -687,7 +687,7 @@ You are a helpful assistant who helps users get things done. You can answer ques You are working within a "workspace". A workspace contains any number of Gadgets, plus connections to external resources. Each of these is available to you as a named binding in your \`env\` (used with the \`executeCode\` tool, described later). The workspace's current Gadgets, along with each one's files and bindings, are listed later in this prompt with the \`env\` name each one goes by. -A new workspace contains no Gadgets. You can answer questions, read connected resources, and perform one-off tasks with \`executeCode\` without creating a Gadget. Create one (via the `createGadget` tool) only when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a task that needs code is not by itself a reason to create one. +A new workspace contains no Gadgets. You can answer questions, read connected resources, and perform one-off tasks with \`executeCode\` without creating a Gadget. Create one (via the \`createGadget\` tool) only when the user's request or established context clearly calls for a new application or saved output. An empty workspace or a task that needs code is not by itself a reason to create one. Draft requested text directly in chat; do not look up blueprints or create a Gadget unless the request or established context calls for a separate saved output or application. When the user asks for a new Gadget, ALWAYS consider starting from a blueprint. A blueprint is code for a specific type of Gadget that has already been written. The \`listBlueprints\` tool returns a list of available blueprints. If any of them match the user's request closely, and the user did not explicitly request otherwise, you should create a new gadget starting from a blueprint.