Skip to main content
Glama

Signal, query, or update a running workflow

workflow_interact

Send signals, run queries, or apply updates to running workflows. Supports fire-and-forget events, synchronous state reads, and mid-execution modifications.

Instructions

Send a signal to or run a query against a running workflow execution.

action=signal: fire-and-forget event; the workflow reacts asynchronously.

  • name: signal name defined in the workflow.

  • input: optional payload matching the signal's schema.

action=query: synchronous read of internal workflow state.

  • name: query handler name defined in the workflow.

  • input: optional parameters for the query.

  • Returns query_name + result inline.

action=update: synchronous request to modify workflow state mid-execution.

  • name: update handler name defined in the workflow.

  • input: optional payload for the update.

  • Returns update_name + result inline.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesInteraction type.
executionIdYesTarget execution ID.
nameYesSignal or query handler name.
inputNoOptional payload for the signal or query.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYes
execution_idYes
messageNoConfirmation message for signal actions.
query_nameNo
update_nameNo
resultNoQuery or update result payload.

Implementation Reference

  • The handler function for the workflow_interact tool. It dispatches based on input.action: 'signal' (fire-and-forget via signalWorkflowExecution), 'query' (synchronous read via queryWorkflowExecution), or 'update' (modify state via updateWorkflowExecution). Returns structured content with appropriate fields for each action type.
      async (input) => {
        try {
          if (input.action === "signal") {
            const res = await mistral.workflows.executions.signalWorkflowExecution({
              executionId: input.executionId,
              signalInvocationBody: {
                name: input.name,
                input: input.input ?? null,
              },
            });
    
            const structured = {
              action: "signal" as const,
              execution_id: input.executionId,
              message: res.message,
            };
    
            return {
              content: [toTextBlock(`Signal '${input.name}' sent to ${input.executionId}: ${res.message}`)],
              structuredContent: structured,
            };
          } else if (input.action === "query") {
            const res = await mistral.workflows.executions.queryWorkflowExecution({
              executionId: input.executionId,
              queryInvocationBody: {
                name: input.name,
                input: input.input ?? null,
              },
            });
    
            const structured = {
              action: "query" as const,
              execution_id: input.executionId,
              query_name: res.queryName,
              result: res.result,
            };
    
            return {
              content: [toTextBlock(`Query '${res.queryName}' on ${input.executionId}: ${JSON.stringify(res.result)}`)],
              structuredContent: structured,
            };
          } else {
            const res = await mistral.workflows.executions.updateWorkflowExecution({
              executionId: input.executionId,
              updateInvocationBody: {
                name: input.name,
                input: input.input ?? null,
              },
            });
    
            const structured = {
              action: "update" as const,
              execution_id: input.executionId,
              update_name: res.updateName,
              result: res.result,
            };
    
            return {
              content: [toTextBlock(`Update '${res.updateName}' on ${input.executionId}: ${JSON.stringify(res.result)}`)],
              structuredContent: structured,
            };
          }
        } catch (err) {
          return errorResult("workflow_interact", err);
        }
      }
    );
  • Output schema (WorkflowInteractOutputShape) for workflow_interact. Defines fields: action (enum signal/query/update), execution_id, message (optional, for signals), query_name/update_name (optional), and result (optional, for query/update payloads).
    export const WorkflowInteractOutputShape = {
      action: z.enum(["signal", "query", "update"]),
      execution_id: z.string(),
      message: z.string().optional().describe("Confirmation message for signal actions."),
      query_name: z.string().optional(),
      update_name: z.string().optional(),
      result: z.unknown().optional().describe("Query or update result payload."),
    };
    export const WorkflowInteractOutputSchema = z.object(WorkflowInteractOutputShape);
  • Input schema for workflow_interact. Defines required inputs: action (enum: signal/query/update), executionId (string), name (string), and optional input (record of strings to unknown).
    inputSchema: {
      action: z.enum(["signal", "query", "update"]).describe("Interaction type."),
      executionId: z.string().min(1).describe("Target execution ID."),
      name: z
        .string()
        .min(1)
        .describe("Signal or query handler name."),
      input: z
        .record(z.string(), z.unknown())
        .optional()
        .describe("Optional payload for the signal or query."),
    },
  • Registration of the workflow_interact tool via server.registerTool(). Includes title, description, inputSchema, outputSchema (WorkflowInteractOutputShape), and annotations. Registered inside the registerWorkflowTools() function.
      // ========== workflow_interact ==========
      server.registerTool(
        "workflow_interact",
        {
          title: "Signal, query, or update a running workflow",
          description: [
            "Send a signal to or run a query against a running workflow execution.",
            "",
            "action=signal: fire-and-forget event; the workflow reacts asynchronously.",
            "  - `name`: signal name defined in the workflow.",
            "  - `input`: optional payload matching the signal's schema.",
            "",
            "action=query: synchronous read of internal workflow state.",
            "  - `name`: query handler name defined in the workflow.",
            "  - `input`: optional parameters for the query.",
            "  - Returns `query_name` + `result` inline.",
            "",
            "action=update: synchronous request to modify workflow state mid-execution.",
            "  - `name`: update handler name defined in the workflow.",
            "  - `input`: optional payload for the update.",
            "  - Returns `update_name` + `result` inline.",
          ].join("\n"),
          inputSchema: {
            action: z.enum(["signal", "query", "update"]).describe("Interaction type."),
            executionId: z.string().min(1).describe("Target execution ID."),
            name: z
              .string()
              .min(1)
              .describe("Signal or query handler name."),
            input: z
              .record(z.string(), z.unknown())
              .optional()
              .describe("Optional payload for the signal or query."),
          },
          outputSchema: WorkflowInteractOutputShape,
          annotations: {
            title: "Interact with running workflow (signal/query/update)",
            readOnlyHint: false,
            destructiveHint: false,
            idempotentHint: false,
            openWorldHint: true,
          },
        },
        async (input) => {
          try {
            if (input.action === "signal") {
              const res = await mistral.workflows.executions.signalWorkflowExecution({
                executionId: input.executionId,
                signalInvocationBody: {
                  name: input.name,
                  input: input.input ?? null,
                },
              });
    
              const structured = {
                action: "signal" as const,
                execution_id: input.executionId,
                message: res.message,
              };
    
              return {
                content: [toTextBlock(`Signal '${input.name}' sent to ${input.executionId}: ${res.message}`)],
                structuredContent: structured,
              };
            } else if (input.action === "query") {
              const res = await mistral.workflows.executions.queryWorkflowExecution({
                executionId: input.executionId,
                queryInvocationBody: {
                  name: input.name,
                  input: input.input ?? null,
                },
              });
    
              const structured = {
                action: "query" as const,
                execution_id: input.executionId,
                query_name: res.queryName,
                result: res.result,
              };
    
              return {
                content: [toTextBlock(`Query '${res.queryName}' on ${input.executionId}: ${JSON.stringify(res.result)}`)],
                structuredContent: structured,
              };
            } else {
              const res = await mistral.workflows.executions.updateWorkflowExecution({
                executionId: input.executionId,
                updateInvocationBody: {
                  name: input.name,
                  input: input.input ?? null,
                },
              });
    
              const structured = {
                action: "update" as const,
                execution_id: input.executionId,
                update_name: res.updateName,
                result: res.result,
              };
    
              return {
                content: [toTextBlock(`Update '${res.updateName}' on ${input.executionId}: ${JSON.stringify(res.result)}`)],
                structuredContent: structured,
              };
            }
          } catch (err) {
            return errorResult("workflow_interact", err);
          }
        }
      );
    }
  • The errorResult helper function used by the workflow_interact handler to return error responses with isError: true flag and a formatted error message.
    export function errorResult(tool: string, err: unknown) {
      const message = err instanceof Error ? err.message : String(err);
      return {
        content: [toTextBlock(`[mistral-mcp:${tool}] ${message}`)],
        isError: true as const,
      };
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-readOnly (write-capable), non-destructive, non-idempotent. The description adds context about each action's behavior: signal is asynchronous, query returns state, update modifies state. This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with bullet points per action, concise and front-loaded. Each sentence adds value, though it could be slightly more terse without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (3 actions, 4 params, output schema exists), the description covers all actions, parameters, and return behavior for query/update. It lacks mention of error cases or prerequisites but is sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% description coverage, but the description adds meaning by explaining the role of 'name' and 'input' per action, and that 'input' is optional. It clarifies the semantic difference between signal, query, and update parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool sends signals, runs queries, or updates a running workflow, distinguishing it from siblings like workflow_execute (start new) and workflow_status (check status). Each action is explained with specific verb+resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance for each action (signal, query, update) and their behaviors (fire-and-forget, synchronous read, synchronous modify). It implies usage context by specifying 'running workflow,' but lacks explicit when-not-to-use or alternative references.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Swih/mistral-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server