Knotbind documentationOpen dashboard
Guide: Write workflow checks

Create multi-step MCP workflows with assertions.

Learn how to design workflow checks that call multiple MCP tools, reference results from earlier steps, and validate responses with JSON Schema assertions.

What is a workflow check?

A workflow check is a sequence of MCP tool calls that validates your server behaves correctly end-to-end. Each step calls one tool, and later steps can reference data from earlier responses.

Example scenario: Search for a customer by email, then fetch that customer's orders using the id the first call returned.

Create your first workflow

Register your server and press Discover tools on its card first. Then open MCP tools in your dashboard, find the Workflow checks panel, and fill in the form:

  1. Name

    A label shown on the workflow card and in alerts (for example Customer order flow).

  2. Steps (JSON)

    A JSON array with one object per step, in the order they run. Press Save workflow when it is ready.

Describe a step

Each step needs a serverId and a toolName:

  • serverId: the id of the registered server the tool lives on, shown as Server id on its card. One workflow can use more than one server.
  • toolName: the tool, exactly as the server advertises it.
  • parameters: the input object passed to the tool. It can use {{'{{'}}name.field{{'}}'}} to refer to an earlier result.
  • extractOutputAs (optional): the name this step's result is stored under, for later steps to use.
  • assertOutput (optional): a JSON Schema the result must match. The step fails if it does not.
  • stopOnFailure (optional): set to false to keep going after this step fails. The default is to stop.
{}
[
  {
    "serverId": "mcp_1",
    "toolName": "search_customers",
    "parameters": { "email": "alice@example.com" },
    "extractOutputAs": "customer",
    "assertOutput": {
      "type": "object",
      "required": ["id"],
      "properties": { "id": { "type": "string" } }
    }
  },
  {
    "serverId": "mcp_1",
    "toolName": "list_orders",
    "parameters": { "customer_id": "{{customer.id}}" }
  }
]

Reference earlier results

Use {{'{{'}}stepName.path{{'}}'}} to inject values from a previous step's result into a later step's arguments.

Example workflow

Step 1: Create a customer

{}
Tool: create_customer
Arguments:
{
  "name": "Alice",
  "email": "alice@example.com"
}

Expected result (schema):
{
  "type": "object",
  "required": ["id"],
  "properties": {
    "id": { "type": "string" }
  }
}

Step 2: Retrieve the customer by ID

{}
Tool: get_customer
Arguments:
{
  "id": "{{create_customer.id}}"
}

Expected result (schema):
{
  "type": "object",
  "required": ["name", "email"],
  "properties": {
    "name": { "const": "Alice" },
    "email": { "type": "string", "format": "email" }
  }
}

The {{'{{'}}create_customer.id{{'}}'}} reference pulls the id field from Step 1's result and injects it into Step 2's arguments.

Write assertions with JSON Schema

The Expected result field uses JSON Schema Draft 2020-12. This lets you validate structure, types, required fields, and value constraints.

Common patterns

Require specific fields

{}
{
  "type": "object",
  "required": ["id", "status"],
  "properties": {
    "id": { "type": "string" },
    "status": { "enum": ["active", "pending"] }
  }
}

Validate array length

{}
{
  "type": "array",
  "minItems": 1,
  "maxItems": 10,
  "items": {
    "type": "object",
    "required": ["name"]
  }
}

Check a field matches a pattern

{}
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
    }
  }
}

Require an exact value

{}
{
  "type": "object",
  "properties": {
    "version": { "const": "2.0" }
  }
}

When a workflow runs

Run once

Press Run once on a workflow card to run it now. The card then shows the time, how it ran, and each step with its duration and the reason if it failed. Only the latest result is kept.

On a schedule

A saved workflow also runs on its own, with the MCP monitor. It uses the same schedule as tool-change checking: weekly on Free, daily on Pro, every 6 hours on Business.

  • Turn the monitor on. In Settings, tick Monitor MCP tool drift. Without it nothing runs on its own, and the workflow card says so. Run once always works.
  • Switch one workflow off. Press Switch off on its card to stop it running on schedule without deleting it.

Stop on first failure

By default a workflow stops at the first step that fails (a tool error, a schema mismatch, or a tool that cannot be called). Later steps are skipped, which prevents cascading failures when a step needs an earlier result. Set stopOnFailure to false on a step to keep going.

Read-only tools only

A workflow calls only tools that the server marks read-only right now. A step is refused if its tool is not read-only, so a workflow never changes your data. To call a tool that changes data, use the one-time tool console, where you approve each call yourself.

When a tool changes

If a tool a workflow calls has changed since you last pressed Discover tools (a new schema, or even a new description), the workflow is not run. Its card shows needs review and says why. Press Discover tools on that server's card to record the tool as it is now, then press Run once.

When a workflow fails

Once a workflow has run more than once, its card also says how many of its last 20 runs passed, and whether each run was scheduled or started by hand.

A scheduled workflow that fails, or is not run because a tool changed, sends one A saved MCP workflow fails alert. It does not repeat while the workflow stays broken, and it alerts again after the workflow has passed and then fails. You can turn this alert off in Settings. A failed workflow does not open a Finding.

Troubleshooting

Step fails: the tool reported an error

The tool answered with an error. The usual causes are a missing required field, a value of the wrong type, or a {{'{{'}}reference{{'}}'}} that points to a field the earlier step did not return. Check the tool's input schema on its card.

Step fails: the output does not match the assertion

The tool returned a result, but it did not match your assertOutput schema. The card names the field or constraint that failed. Either update the schema to match what the tool really returns, or fix the tool if the result is wrong.

A reference is not resolved

A {{'{{'}}name.field{{'}}'}} reference was not replaced. Check that the name matches an extractOutputAs on an earlier step, that the field exists in that step's result, and that the earlier step passed, because a failed step stores nothing.

Best practices

  • Start simple: Test one tool at a time before chaining several steps.
  • Name results clearly: Use extractOutputAs names such as customer or order, not result1.
  • Validate structure, not exact values: Assertions should focus on "type", "required", and "enum" rather than brittle "const" checks on dynamic data.
  • Keep workflows focused: One workflow per feature or user journey.
  • Run once before you rely on the schedule. Catch a bad parameter or assertion early.

Next steps