Files
windmill/system_prompts
hugocasaandClaude Opus 5.5 2e4c0789a2 feat: agent to flow, tabbed agent page, one webhook panel with an AI prompt (#11903)
* feat: open a flow linking an agent from its menu

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: toast when the flow handoff cannot be stored

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: turn an agent into a flow from its editor, and into a chat app from its page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: let sandboxed apps run agents, and keep the flow handoff race-free

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: save the new flow as a draft before letting the agent draft go

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: offer the chat app only to those who may build apps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: give the agent page's chat app section a tab on small screens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: show the flow handoff as an info alert, framed around context and output

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the flow handoff from operators and say why the chat app is locked

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: collapse the flow handoff hint to its title and button

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: show the flow handoff as a corner hint, as the flow editor shows its own

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: name the agent on the app button and say why it is disabled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: ask whether the agent needs steps before or after it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: name what a flow adds around the agent in its hint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: say a never-deployed agent turns into a flow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* revert: leave agent runs and the raw-app guidance to the chat SDK's runnable transport

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: show the agent page's sections as tabs at every width, as a chat-mode flow's page does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: one webhook panel for scripts, flows and agents, with an AI prompt and chat-mode examples

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: describe the preprocessor's event argument instead of the v1 wm_trigger

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: give the flow chat's preprocessor example the v2 event signature

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: group a webhook's request choices and examples under an HTTP tab, beside the AI prompt and chat SDK

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: drop a comment about guidance this branch no longer adds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: say where the AI prompt expects the webhook token

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: tell the chat-flow prompt that memory_id is required

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the webhook tabs next to their content

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the webhook's REST tab name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: build an agent's chat app from a template, not an AI session

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: don't send the agent chat app's message on an IME confirmation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: agent API tab with one row of call examples and a copy-prompt button

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: open build app in an AI session when AI sessions are on

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: app conversations through the memory_id query parameter, chat-mode flows included

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: regenerate the mcp session instructions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: type backendAsync's memoryId option in the eval diagnostics

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: pin git-sync hub scripts to windmill-cli 1.849.0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep build app in the editor when windmill ai is off

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: webhook panel with http and chat sdk tabs over toggle settings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: memoryId option on the sync backend call too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: bump the ui builder artifact for the memoryId option

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the webhook panel's http and chat sdk tabs close to their content

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: shared-utils 1.0.14

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: cli takes shared-utils 1.0.14 for the memoryId option

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: pin the app conversation scoping and the memoryId signatures

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: assert the ownership refusal, not any refusal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: match the memoryId option in the cli wmill.ts signature tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: show the webhook request formats in a card with their toggle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: put the chat sdk example in the same card as the http request

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: add a windmill app tab to chat-mode flow pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: title the webhook example cards and label the ai prompt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: offer the chat app from the conversations sidebar instead of a tab

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: raise the chat app's chat-sdk floor to 1.851.0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: render the agent's chat app card only once the workspace is known

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: gate the flow's build chat app menu item like the sidebar card

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: build the agent's chat app through the page's navigation, for app-only authors too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep an imported app in the editor inside a session preview

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: build a form app from an agent without managed memory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: cover the agent form app's generated source

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:32:20 +01:00
..

System Prompts

The single source of the AI guidance Windmill ships: what an agent needs to know about Windmill itself to write flows, scripts, apps, pipelines, resources, triggers and schedules. Two consumers are built from it:

  • the chat (the frontend AI chat: flow, script, app and global modes), through the $system_prompts alias to auto-generated/;
  • the CLI (wmill init / wmill refresh prompts), as the skills embedded in cli/src/guidance/skills.gen.ts, next to the AGENTS.wmill.md template in cli/src/guidance/core.ts.

The workspace MCP server (backend/windmill-api/src/mcp/session/) is a third reader, one step removed: it serves the global chat's own get_instructions texts and system prompt, rendered for an external client by npm run gen:mcp-session in frontend/. Rerun that after generate.py.

Guidance written in one consumer only is guidance the other never gets. Write it here.

Structure

system_prompts/
├── base/              # Hand-written guidance, one file per topic (flow-base.md, raw-app.md, …)
│                      # plus CLI-only intros (flow-cli.md, script-cli.md, raw-app-cli.md, …)
├── languages/         # Hand-written per-language guidance (bun.md, python3.md, …)
├── generate.py        # Builds everything under auto-generated/ and cli/src/guidance/skills.gen.ts
├── utils.py           # Shared helpers, including the fence renderer
└── auto-generated/    # Generated — never edit
    ├── prompts.ts     # One export per base/ and languages/ file (chat render), SDK docs, schema
    ├── index.ts       # Chat helpers (getFlowPrompt, getScriptPrompt, …)
    ├── skills/        # One SKILL.md per CLI skill (cli render)
    ├── sdks/          # SDK reference extracted from the TypeScript and Python clients
    └── cli/           # CLI command reference extracted from cli/src/commands/

How a topic is assembled

TOPICS in generate.py lists, for each topic, the parts both consumers concatenate in order: a file under base/ or languages/, or a token filled per consumer ({lang}, {sdk}, {wac_sdk}, {openflow_schema}, {cli_commands}). The same entry produces the topic's chat helper in index.ts and its CLI skill, so a part added there reaches both. A part tagged ('chat', …) or ('cli', …) goes to that consumer only, and cli_intro heads the CLI skill with a CLI-only workflow file (flow-cli.md, script-cli.md, raw-app-cli.md).

Topic Chat helper CLI skill Shared parts
script getScriptPrompt(lang) write-script-<lang> script-base.md, the language file, its SDK
flow getFlowPrompt() write-flow flow-base.md, the OpenFlow schema
raw app getRawAppPrompt(lang) raw-app raw-app.md (chat adds the SDK)
resources getResourcePrompt() resources resources.md
workflow-as-code getWorkflowAsCodePrompt(lang) write-workflow-as-code workflow-as-code.md, the WAC SDK
pipeline getPipelinePrompt() write-pipeline pipeline-base.md
data tables getDatatablePrompt() datatables datatable.md
workspace settings getWorkspaceSettingsPrompt() workspace-settings workspace-settings.md
triggers, schedules, preview, CLI commands — same names CLI only

The app chat embeds RAW_APP_BASE directly (chat/app/core.ts).

Consumer fences

A sentence that only one consumer should see stays in the shared file, fenced:

A tool name outside that character set fails every run of the flow.
<!-- chat-only -->
The flow write tools refuse such a name.
<!-- /chat-only -->
<!-- cli-only -->
`wmill lint <flow folder>` reports it before anything runs.
<!-- /cli-only -->

render_for (utils.py) renders every file once per consumer: prompts.ts gets the chat render, the skills get the cli render, and the fence lines reach neither. Fences sit on their own lines and cannot nest; an unbalanced or misspelled fence fails generation (an HTML comment opening with cli or chat, or ending in only, is read as a fence attempt).

Use a fence for a sentence or a section. When most of a topic differs per consumer, a CLI-only file used as cli_intro reads better than a file that is mostly fences.

What goes where

  • Here: anything true of Windmill regardless of who is asking — module shapes, data flow rules, what the editor accepts, how data tables, secrets or app access work.
  • In the chat's TypeScript prompt builders (frontend/src/lib/components/copilot/chat/*/core.ts): only tool plumbing (which tool to call, its arguments) and values known at run time (the user's name, this app's data-table policy, session capabilities).
  • In cli/src/guidance/core.ts (AGENTS.wmill.md): project-level CLI workflow — which skill to use, deploying, debugging jobs.

A file in TOPICS names no chat tool, not even inside a chat-only fence: it reaches every chat mode (flow mode's system prompt, global mode's get_instructions), each with its own tool names, and global/sessionToolset.test.ts fails a prompt that names a tool its session lacks. Describe the action instead ("the flow write tools refuse such a name") and name the tool in TypeScript. The one exception is flow-chat-special-modules.md, which only flow mode reads.

Regenerating

After editing anything here, or when SDK methods, the OpenFlow schema or CLI commands change:

python system_prompts/generate.py

CI (.github/workflows/check-system-prompts.yml) runs system_prompts/check-freshness.sh, which fails when the committed output is stale.

To also refresh the standalone skills in a Claude plugin checkout:

python system_prompts/generate.py --plugin-dir ~/windmill-claude-plugin

--plugin-dir accepts:

  • the windmill-claude-plugin repo root
  • a plugin root such as plugins/windmill
  • a direct skills/ directory

To regenerate the public docs repo (consumed by context7):

python system_prompts/generate.py --context7-dir ~/windmill-cli-docs

--context7-dir writes a fully-rendered snapshot (AGENTS.md, cli-commands.md, skills/<name>/SKILL.md, README.md, manifest.json with the Windmill version) with all template placeholders resolved — suitable for ingestion by docs aggregators. In CI this runs from .github/workflows/publish-cli-docs.yml on every release tag. The generator refuses to wipe the target directory unless it's empty or has a context7 marker (context7.json, manifest.json, or a windmill-cli-docs git remote), so a typo can't delete unrelated files.