Skip to content

Workflow packages ​

Each discoverable workflow is an immediate child directory of WORKSPACE_ROOT/workflows. It contains a mandatory manifest.yaml, a referenced flow file, and optional scripts, prompts, or fixtures.

Server startup uses strict discovery by default: invalid workflow or driver packages fail startup. Set WORKSPACE_DISCOVERY_MODE=degraded to retain healthy packages; skipped items are logged and make /ready report a degraded state.

Manifest ​

yaml
schemaVersion: 1
id: summarize-document
name: Summarize document
description: Produce a concise summary.
flow: flow.yaml
permissions:
  tools: []
webhook:
  endpoints:
    base: async
  request:
    type: json
    inputSchema:
      fields:
        - name: document
          type: textarea
          required: true
schedule:
  inputSchema:
    fields:
      - name: document
        type: textarea
        required: true

id is lower-kebab-case and must equal the directory name. flow is relative and cannot escape the workflow directory. Scheduled workflows cannot use multipart-file or require any multipart file field (minItems must be omitted or 0). Add tool metadata to expose the workflow as a composable tool; tool names are unique and cannot contain /.

permissions is optional. If omitted, it is treated as tools: [].

tool.authorization.grants and schedule.authorization.grants may reference capability IDs declared in permissions.tools. Grant IDs must be unique per trigger and every referenced ID must exist in the manifest capability list.

yaml
schemaVersion: 1
id: post-document
name: Post document
description: Post one document and archive it.
flow: flow.yaml
permissions:
  tools:
    - id: post
      tool: accounting/post
    - id: archive
      tool: storage/archive
tool:
  name: documents/post-and-archive
  description: Post and archive a document.
  inputSchema:
    type: object
  authorization:
    grants: [post, archive]
schedule:
  authorization:
    grants: [archive]

Use multipart-file for the backward-compatible single-file input. Use multipart when a webhook needs text fields and repeated files:

yaml
request:
  type: multipart
  inputSchema:
    fields:
      - name: prompt
        type: textarea
        required: false
  fileFields:
    - name: attachments
      minItems: 0
      maxItems: 10
      maxBytes: 26214400
      allowedMimeTypes: ["*/*"]
  maxTotalBytes: 104857600

Each file is exposed through flow.input as { filename, mimeType, size, data }, where data is base64. Repeating a text field, exceeding count or size limits, sending an empty file, or using a MIME type outside its allowlist rejects the request before execution. A multipart webhook also accepts JSON when no files are supplied, allowing text-only callers to avoid multipart encoding.

Flow document ​

yaml
summary: Summarize a document
version: 1
start: summarize
nodes:
  - id: summarize
    type: llm-prompt
    model:
      role: summarization
    input:
      document:
        expr: context.input.document
    outputSchema:
      type: string
connections: []

Node IDs are unique. Connections reference existing nodes and may include a route for branching nodes. The graph must be reachable from start, obey each node type's structural rules, and avoid uncontrolled cycles.

version in flow.yaml is optional metadata. Current runtime validation accepts numeric or string values and does not change execution behavior by version value.

External files ​

Script and prompt nodes accept bounded workflow-relative file references:

yaml
- id: prepare
  type: script
  script:
    source:
      inline: prepare.ts

- id: summarize
  type: llm-prompt
  prompt:
    inline: summarize.md

Resolution is relative to flow.yaml; absolute paths and traversal outside the configured root fail loading. The inline property is supported only at script.source.inline and prompt.inline.

Discovery lifecycle ​

Packages are scanned on server startup. Additions and edits take effect after restart.

In lenient discovery mode, startup continues when a package is invalid (for example missing manifest.yaml, invalid manifest schema, unresolved workflow dependency, or dependency cycle). The server logs one warning per skipped package with directory and error context.

When embedding @faimulus/core, discoverWorkflows is strict by default and throws on invalid packages unless called with { strict: false }.

Documentation for the current repository state.