Skip to main content

warpp-workflow-authoring

Author WARPP workflows for Manifold as typed-port dataflow JSON. Use when a user asks to build, create, design, generate, or edit a Flow / workflow / automation / pipeline / DAG in Manifold, or mentions WARPP, workflow nodes, or the /flow builder. Covers the document format, port types and coercions, the builtin node catalog, control flow (if/coalesce/map), and the workflow_catalog then workflow_save validate-and-self-correct loop.

معلومات المصدر

المستودع
intelligencedev/manifold
آخر نشاط في المصدر
١٢ يوليو ٢٠٢٦ في ٢١:٤٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٠٢
التفرعات
٣١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
warpp-workflow-authoring
description
Author WARPP workflows for Manifold as typed-port dataflow JSON. Use when a user asks to build, create, design, generate, or edit a Flow / workflow / automation / pipeline / DAG in Manifold, or mentions WARPP, workflow nodes, or the /flow builder. Covers the document format, port types and coercions, the builtin node catalog, control flow (if/coalesce/map), and the workflow_catalog then workflow_save validate-and-self-correct loop.
metadata
{"short-description":"Build and validate WARPP workflow JSON documents for Manifold."}
# Authoring WARPP Workflows WARPP is Manifold's typed-port dataflow engine. A workflow is a directed acyclic graph of nodes. **Data moves only through typed wires or literals — there are no expressions.** Your job is to produce a valid workflow *document* (JSON) and prove it valid with `workflow_save`. ## The one rule Every node is a pure function with declared, typed input and output ports. An input binding is **exactly one of**: - `{"from": "nodeID.port"}` — a wire from an upstream node's output port - `{"value": <literal>}` — a fixed literal typed into the node Never both. Never an expression string, template, or `${...}`. To reshape data, use a data node (`data.extract`, `data.template`, `data.parse`, …). ## The authoring loop (do this every time) 1. **Discover tools with `tool_search`.** For every step that performs an external action (web search/fetch, file I/O, calling an API or another agent, sending a message, RAG, an MCP capability, …), call `tool_search` with a natural-language description of the capability you need — e.g. `"search the web"`, `"read a file"`, `"query a database"`, `"send a slack message"`. The user may have configured MCP servers that publish tools you cannot know ahead of time, so **do not assume a tool exists or guess its name** — search, then pick the best-matching result for the step. If several match, choose the most specific/appropriate one. 2. **`workflow_catalog`** — fetch the live node manifests for the tools you chose (plus the builtins), their exact port names/types, and the coercion table. Every registry tool is available as a node typed `tool.<name>`. **Never guess a node type or a port name — read them from the catalog.** 3. **Build the document** (shape below). Prefer wiring (`from`) over literals for anything that should be dynamic. 4. **`workflow_save`** — it validates and returns diagnostics. If any come back, fix each one (they carry a `code`, `message`, and `path`) and save again. Do not stop until it saves with no error diagnostics. 5. **`workflow_run`** (only if asked to test) — runs it and returns the declared outputs. Discover → build → validate → self-correct. Do not hand back an unvalidated document, and do not invent a tool you did not find via `tool_search` or the catalog. ## Document shape ```json { "id": "research-brief", "name": "Research brief", "inputs": [{ "name": "topic", "type": "text", "required": true }], "nodes": [ { "id": "search", "type": "tool.web_search", "inputs": { "query": { "from": "in.topic" }, "max_results": { "value": 5 } } }, { "id": "summary", "type": "llm.generate", "inputs": { "instruction": { "value": "Summarize as 5 bullets." }, "input": { "from": "search.results_text" } } } ], "outputs": { "brief": { "from": "summary.text" } } } ``` - `id` matches `^[a-zA-Z0-9_-]+$`; `name` is human-readable. - `inputs` are the workflow's typed parameters, exposed to nodes as `in.<name>` (e.g. `{"from": "in.topic"}`). - Each node has a unique `id`, a `type` from the catalog, and an `inputs` map keyed by the manifest's input port names. - `outputs` maps result names to node output ports; this is the run result. - `in` and `item` are reserved node ids. - Optional: `settings.max_concurrency` (default 4); `publish.tool: true` to expose the workflow as an agent tool; `project_id` to scope file tools to a project. ## Types and coercions Port types: `text`, `number`, `boolean`, `json`, `file`, `list<T>` (T is any scalar). The **only** implicit coercions, applied to wires, are: - `number → text` - `boolean → text` Nothing else coerces. `json → text` needs `data.stringify`; `text → json` needs `data.parse`; pull a field out of `json` with `data.extract`. **Literals must match the port type exactly** (`"5"` for a text port, `5` for a number port). A `file` port accepts a literal path string. ## Builtin nodes (stable; always available) | Type | Inputs | Outputs | |---|---|---| | `data.extract` | `source: json`, `path: text`, `as: text` (default `"json"`) | `value` (typed by `as`) | | `data.template` | `template: text`, `vars` (named, any type) | `text: text` | | `data.merge` | `objects` (list of `json`) | `json: json` | | `data.stringify` | `value: T` | `text: text` | | `data.parse` | `text: text` | `json: json` | | `data.constant` | `value: json`, `as: text` (default `"json"`) | `value` (typed by `as`) | | `logic.if` | `condition: boolean`, `value: T` | `then: T`, `else: T` (one fires) | | `logic.coalesce` | `values` (list of `T`) | `value: T` (first that fired) | | `logic.equals` | `a: T`, `b: T` | `result: boolean` | | `logic.contains` | `haystack: text`, `needle: text` | `result: boolean` | | `logic.not` | `value: boolean` | `result: boolean` | | `logic.greater_than` | `a: number`, `b: number` | `result: boolean` | | `control.map` | `items: list<T>`, `concurrency: number`, `on_item_error: text` | `results: list<…>` | | `llm.generate` | `instruction: text`, `input: text`, `model: text` | `text: text` | **Tool nodes** are `tool.<name>` — one for every tool in the registry, including MCP-server tools (e.g. `tool.web_search`, `tool.file_write`, `tool.brave_brave_web_search`). The set is instance-specific and not known in advance, so **find tools with `tool_search`** (by capability) rather than assuming; then use the match as node type `tool.<its name>`. Each tool node has a `result: json` output plus, for curated tools, typed outputs. Get the exact input/output ports from `workflow_catalog`. `data.extract` / `data.constant` set their output type via the `as` config: one of `text`, `number`, `boolean`, `json`, `list<json>`. ## Named-variadic and list-variadic ports - `data.template.vars` is **named-variadic**: an object of bindings, one per `{placeholder}` in the template — `"vars": { "topic": {"from":"in.topic"}, "n": {"value": 3} }`. - `logic.coalesce.values` and `data.merge.objects` are **list-variadic**: an array of bindings — `"values": [ {"from":"a.text"}, {"from":"b.text"} ]`. ## Control flow (gated wires, not conditionals) - `logic.if` fires **exactly one** of `then` / `else` per run based on `condition`. - A node whose **required** input never fires (e.g. it reads the branch that didn't fire) is **skipped**, and skips cascade downstream. An **optional** input whose source is skipped falls back to its default. - `logic.coalesce` rejoins branches: it emits the first of its inputs that actually fired. - `control.map` fans out over `items: list<T>`: its `body` subgraph runs once per item, seeing `item.value` and `item.index`, and gathers the body's single `result` output into `results`. `on_item_error` is `fail` (default) or `skip`. Bodies may also wire from outer / `in` ports. ## Common mistakes to avoid - Assuming a tool exists or guessing its name. Use `tool_search` to find the right tool (MCP servers add tools you can't know in advance), then read its exact ports from `workflow_catalog`. - Using an expression / template string in a binding. Use a `data.*` node. - Wiring `json` into a `text` port (or vice-versa) without a `data.stringify` / `data.parse` / `data.extract` between them. - A literal whose JSON type doesn't match the port (e.g. `5` into a text port). - Forgetting `data.template.vars` is a named object and `logic.coalesce.values` is an array. - Returning a document without running it through `workflow_save`. ## More examples Read `references/examples.md` (via `skill_read`, path `references/examples.md`) for full worked documents: a linear pipeline, an if/coalesce branch, and a map fan-out.
عرض على GitHub