Files
windmill/system_prompts/base/agent.md
T
hugocasaandClaude Opus 5.5 8dd46a4d14 feat: build, test and run standalone ai agents from ai sessions (#11954)
* feat: guidance for building standalone ai agents in ai sessions

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

* fix: agent guidance for resource-only sessions, no flow tools

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

* fix: tell the user to deploy a drafted tool script with its agent

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

* fix: scope plain agent values, document tool_inputs, list agents in get_instructions

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

* feat: test and run ai agents from ai sessions, open agents in their editor

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

* fix: full-bleed agent editor tabs, back to the run form for agent tests

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

* fix: describe read-and-run as running agents too, pin agent run links

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

* feat: host the agent editor natively in session tabs

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

* fix: switch the agent editor to tabs below 900px

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

* fix: name an agent's session tab after its summary

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

* feat: show deployed agents in session tabs, open and run them from the chat

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

* feat: deploy agents from the chat, report agent tabs as the active editor

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

* feat: pick agents from the tab picker, name their tabs, scope the agent page to its workspace

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

* fix: leave open editors alone on agent writes, read the agent page's workspace user

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

* fix: refresh an agent's deployed page when the chat deploys or deletes it

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

* fix: name agent tabs before they load, mark agents in the changes drawer, stay on a deleted agent's tab

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

* fix: keep a cleared agent summary out of its tab name

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

* fix: keep the resource drawer's json option that the resources list still passes

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

* feat: open an agent in an AI session from its pages, fix review findings on agent tabs

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

* docs: name the reserved agent tool names in the agent guidance

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

* fix: reload an agent's editor on a discard, open a new agent in a session

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

* fix: show agents as agents on compare and deploy, name a never-deployed one by its path

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

* fix: keep a deployed agent's type in its draft diff

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

* fix: link a fork row to the agent editor only on the side that holds the agent

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

* fix: guard agent page paths, mark drafted agents in the picker, side-aware agent rows on fork compare

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:46:43 +01:00

5.8 KiB

Windmill AI Agents

An agent, as the Agents page lists it, is a saved LLM with its own system prompt, tools and memory, stored as a resource of type ai_agent. It is built once and used in several places: it is run from its own page (a chat, or a run form), a flow's AI agent step links to it by path, and it can be shared in Slack channels from its page. Build a standalone agent when the user wants an assistant they talk to or reuse. Build a flow when the agent is one step of a larger process.

File Format

An agent is a resource file like any other, {path}.resource.yaml (or .resource.json), with resource_type: ai_agent.

Structure

{
  "resource_type": "ai_agent",
  "description": "Answers support questions from the product docs",
  "value": {
    "provider": { "kind": "openai", "resource": "$res:f/ai_providers/openai", "model": "gpt-4o" },
    "system_prompt": "You are the support assistant for Acme. Answer from the docs; say so when they don't cover a question.",
    "memory": { "kind": "compaction" },
    "output_type": "text",
    "tools": [
      {
        "id": "search_docs",
        "summary": "search_documentation",
        "description": "Search the product documentation. Use it whenever the user asks how a feature works.",
        "value": {
          "tool_type": "flowmodule",
          "type": "script",
          "path": "f/support/search_docs",
          "input_transforms": {
            "query": { "type": "ai" },
            "index": { "type": "static", "value": "product_docs" }
          }
        }
      }
    ]
  }
}

The agent's own settings are plain values, not the input_transforms an agent step in a flow uses: each is fixed when the agent is saved. Only a tool's arguments keep input_transforms (see Tools). $res: and $var: references inside it are resolved at run time.

  • provider (required): { "kind", "resource": "$res:<path>", "model" }, plus an optional reasoning_effort. resource names the workspace's AI provider resource of that kind
  • system_prompt: how the agent behaves. Write it for the agent's job: who it serves, what it may do with its tools, and what it should refuse or hand back
  • memory: what lets the agent see earlier turns. { "kind": "compaction" } keeps the whole conversation, summarizing its older part as it nears the model's context window; it is what a new agent starts with on its page. { "kind": "off" } makes every run start from nothing, right for an agent that handles one request per run
  • output_type: text (default) or image. Image output ignores tools and needs S3 storage on the workspace
  • output_schema: a JSON schema the answer must follow, for an agent whose output a program reads
  • max_iterations: how many model and tool rounds a run may take, 1 to 1000 (default 10)
  • streaming (default on), temperature, max_completion_tokens: as their names say
  • run_on_behalf_of: runs from the agent's page take the identity the agent was deployed with rather than the caller's, so people can use it without access to what its tools touch. slack_anyone lets anyone in the Slack channels it is shared in ask it, and is kept only with run_on_behalf_of. Set either only when the user asks: both widen who acts with the deployer's rights
  • on_behalf_of is the identity itself. Deploying sets it, so never write it

Tools

tools takes the same entries as a flow's AI agent step. value.tool_type is flowmodule for a script or inline script the agent calls (or a nested agent or AI decision), mcp for an MCP server ({ "tool_type": "mcp", "resource_path": "$res:<path>", "include_tools": [], "exclude_tools": [] }), or websearch for web search ({ "tool_type": "websearch" }, summary Web Search).

  • Write logic made for this agent as an inline rawscript tool, as a flow writes its steps. Point a script tool at a deployed script (path) only when one already does the job: a run calls the deployed version, so a script that exists only as a draft fails the run. An inline tool's value is a flow's rawscript step: { "tool_type": "flowmodule", "type": "rawscript", "language": "bun", "content": "export async function main(query: string) { ... }", "input_transforms": { "query": { "type": "ai" } } }
  • A flow cannot be a tool: a run offered one fails with Unsupported tool. Wrap it in a script that runs the flow
  • A flowmodule tool's summary is the name the agent calls it by: letters, numbers and underscores only, unique among the agent's tools, and neither a reserved step id (a JavaScript keyword, ctx, state, bg) nor __wm_web_search. Put the explanation in description, which tells the agent when to call it
  • Each argument of a tool is either the model's or fixed. { "type": "ai" } (or no value) lets the model fill it; a static value fixes it and hides it from the model. Fix what the model must not choose, such as a resource, a table name or a limit

Using It From a Flow

An AI agent step links to a saved agent with value.agent instead of carrying its own provider, system prompt and tools:

{
  "id": "support",
  "value": {
    "type": "aiagent",
    "agent": "f/support/support_agent",
    "input_transforms": {
      "user_message": { "type": "javascript", "expr": "flow_input.question" }
    },
    "tools": []
  }
}

The step holds only what belongs to one use of the agent: user_message, user_attachments, enabled_tools, memory_id, previous_messages, and the model and reasoning_effort overrides. Its value.tool_inputs ({ "<tool id>": { "<argument>": <input transform> } }) wires a saved tool's arguments to this flow, e.g. flow_input.customer_id, over the transforms the agent saved, without changing the agent. Everything else comes from the agent, so a change to the agent reaches every flow linking it.