kind: tool-call

agentRole: orchestrator

toolName: build-workflow-with-agent

task: Build a workflow named "INS-164 mocked credential guard" with a Manual Trigger connected to a Slack node that posts a message. Use a mocked slackApi credential placeholder directly in the workflow SDK — do not call credentials setup or ask for a real Slack credential. The builder must submit the workflow and verify it with verify-built-workflow. After verification reports the mocked credential setup state, stop.

conversationContext: User wants to test the mocked credential guard behavior. The workflow should use a placeholder/mocked slackApi credential, not a real one. The builder should not call credentials setup. Verification should surface the mocked credential setup state.

result: Workflow build started (task: build-bdb45b93). Reply with one short sentence — e.g. name what's being built. Do NOT summarize the plan or list details.


agentRole: workflow-builder

toolName: nodes

query: Slack

description: Consume Slack API

channel

operations: archive close create get get_all history invite join kick leave member open rename replies set_purpose set_topic unarchive

message

operations: delete get_permalink post search send_and_wait update

description: Request human approval for tools

description: Consume Slack API

channel

operations: archive close create get get_all history invite join kick leave member open rename replies set_purpose set_topic unarchive

message

operations: delete get_permalink post search send_and_wait update


content:
/**
 * Slack Node - Version 2.4
 * Discriminator: resource=message, operation=post
 */

interface Credentials {
  slackApi: CredentialReference;
  slackOAuth2Api: CredentialReference;
}

export type SlackV24MessagePostParams = {
  resource: 'message';
  operation: 'post';
  authentication?: 'accessToken' | 'oAuth2' | Expression<string>;
/**
 * Send Message To
 */
    select: 'channel' | 'user' | Expression<string>;
/**
 * The Slack channel to send to
 * @searchListMethod getChannels
 * @displayOptions.show { select: ["channel"] }
 * @default {"mode":"list","value":""}
 */
    channelId?: { __rl: true; mode: 'list' | 'id' | 'name' | 'url'; value: string; cachedResultName?: string };
/**
 * User
 * @searchListMethod getUsers
 * @displayOptions.show { select: ["user"] }
 * @default {"mode":"list","value":""}
 */
    user?: { __rl: true; mode: 'list' | 'id' | 'username'; value: string; cachedResultName?: string };
/**
 * Whether to send a simple text message, or use Slack’s Blocks UI builder for more sophisticated messages that include form fields, sections and more
 * @default text
 */
    messageType?: 'text' | 'block' | 'attachment' | Expression<string>;
/**
 * The message text to post. Supports markdown by default - this can be disabled in "Options".
 * @displayOptions.show { messageType: ["text", "block"] }
 */
    text: string | Expression<string>;
/**
 * Enter the JSON output from Slack's visual Block Kit Builder here. You can then use expressions to add variable content to your blocks. To create blocks, use Slack's Block Kit Builder
 * @hint To create blocks, use Slack's Block Kit Builder
 * @displayOptions.show { messageType: ["block"] }
 */
    blocksUi: string | Expression<string>;
/**
 * Attachments
 * @displayOptions.show { messageType: ["attachment"] }
 * @default {}
 */
    attachments?: Array<{
    /** Required plain-text summary of the attachment
     */
    fallback?: string | Expression<string>;
    /** Text
     */
    text?: string | Expression<string>;
    /** Title
     */
    title?: string | Expression<string>;
    /** Title Link
     */
    title_link?: string | Expression<string>;
    /** Color of the line left of text
     * @default #ff0000
     */
    color?: string | Expression<string>;
    /** Text which appears before the message block
     */
    pretext?: string | Expression<string>;
    /** Name that should appear
     */
    author_name?: string | Expression<string>;
    /** Author Link
     */
    author_link?: string | Expression<string>;
    /** Icon which should appear for the user
     */
    author_icon?: string | Expression<string>;
    /** Image URL
     */
    image_url?: string | Expression<string>;
    /** Thumbnail URL
     */
    thumb_url?: string | Expression<string>;
    /** Text of footer to add
     */
    footer?: string | Expression<string>;
    /** Icon which should appear next to footer
     */
    footer_icon?: string | Expression<string>;
    /** Timestamp of the message to post
     * @default 0
     */
    ts?: number | Expression<number>;
    /** Fields to add to message
     * @default {}
     */
    fields?: {
        /** Item
     */
    item?: Array<{
      /** Title
       */
      title?: string | Expression<string>;
      /** Value
       */
      value?: string | Expression<string>;
      /** Whether items can be displayed next to each other
       * @default true
       */
      short?: boolean | Expression<boolean>;
    }>;
  };
  }>;
/**
 * Other options to set
 * @default {}
 */
    otherOptions?: {
    /** Whether to append a link to this workflow at the end of the message. This is helpful if you have many workflows sending Slack messages.
     * @default true
     */
    includeLinkToWorkflow?: boolean | Expression<boolean>;
    /** Set an image or an emoji as the Profile Photo (avatar) of the bot sending the message. Will not be used if sending message as a user.
     * @default {"imageValues":[{"profilePhotoType":""}]}
     */
    botProfile?: {
        /** Add Bot Profile Photo
     */
    imageValues?: {
      /** Profile Photo Type
       */
      profilePhotoType?: 'image' | 'emoji' | Expression<string>;
      /** Only used if sending message as a bot. Use emoji codes like +1, not an actual emoji like 👍. List of common emoji codes
       * @displayOptions.show { profilePhotoType: ["emoji"] }
       */
      icon_emoji?: string | Expression<string>;
      /** Only used if sending message as a bot
       * @displayOptions.show { profilePhotoType: ["image"] }
       */
      icon_url?: string | Expression<string>;
    };
  };
    /** Whether to turn @users and #channels in message text into clickable links
     * @default false
     */
    link_names?: boolean | Expression<boolean>;
    /** Provide another message's Timestamp value to make this message a reply
     * @default {}
     */
    thread_ts?: {
        /** Reply to a Message
     */
    replyValues?: {
      /** Message timestamps are included in output data of Slack nodes, abbreviated to ts
       */
      thread_ts?: number | Expression<number>;
      /** Whether the reply should be made visible to everyone in the channel or conversation
       * @default false
       */
      reply_broadcast?: boolean | Expression<boolean>;
    };
  };
    /** Whether to use Slack Markdown to format the message
     * @default true
     */
    mrkdwn?: boolean | Expression<boolean>;
    /** Whether to enable unfurling of primarily text-based content
     * @default false
     */
    unfurl_links?: boolean | Expression<boolean>;
    /** Whether to disable unfurling of media content
     * @default true
     */
    unfurl_media?: boolean | Expression<boolean>;
    /** Whether to send a temporary, ephemeral message
     * @displayOptions.show { /select: ["channel"] }
     * @default {}
     */
    ephemeral?: {
        /** Send as Ephemeral Message
     */
    ephemeralValues?: {
      /** User to Send
       * @searchListMethod getUsers
       * @default {"mode":"list","value":""}
       */
      user?: { __rl: true; mode: 'list' | 'id'; value: string; cachedResultName?: string };
      /** Whether to send a temporary, ephemeral message
       * @default true
       */
      ephemeral?: boolean | Expression<boolean>;
    };
  };
    /** Whether to send a temporary, ephemeral message
     * @displayOptions.show { /select: ["user"] }
     * @default true
     */
    ephemeral?: boolean | Expression<boolean>;
    /** The message will be sent from this username (i.e. as if this individual sent the message). Add chat:write.customize scope on Slack API
     * @displayOptions.show { /authentication: ["accessToken"] }
     */
    sendAsUser?: string | Expression<string>;
  };
};

export type SlackV24MessagePostOutput = {
  channel?: string;
  message?: {
    app_id?: string;
    blocks?: Array<{
      block_id?: string;
      elements?: Array<{
        elements?: Array<{
          style?: {
            italic?: boolean;
          };
          text?: string;
          type?: string;
          url?: string;
        }>;
        type?: string;
      }>;
      type?: string;
    }>;
    bot_id?: string;
    bot_profile?: {
      app_id?: string;
      deleted?: boolean;
      icons?: {
        image_36?: string;
        image_48?: string;
        image_72?: string;
      };
      id?: string;
      name?: string;
      team_id?: string;
      updated?: number;
    };
    team?: string;
    text?: string;
    ts?: string;
    type?: string;
    user?: string;
  };
  message_timestamp?: string;
  ok?: boolean;
};

export type SlackV24MessagePostNode = {
  type: 'n8n-nodes-base.slack';
  version: 2.4;
  credentials?: Credentials;
  config: NodeConfig<SlackV24MessagePostParams>;
  output?: Items<SlackV24MessagePostOutput>;
};


toolName: workflows

query: INS-164 mocked credential guard


toolName: submit-workflow

guidance: Workflow submission failed due to an internal or service error. Stop editing and ask the user to retry or check instance health.

errors: Workflow save failed: Workflow structure is invalid. nodes[0].parameters (invalid_type): Expected object, received null


task: Build a workflow named "INS-164 mocked credential guard" with a Manual Trigger connected to a Slack node that posts a message. Use a mocked slackApi credential placeholder directly — do not call credentials setup or request a real Slack credential. IMPORTANT: every node's `parameters` field must be a plain object `{}` (never null), even if the node has no configurable parameters. The Manual Trigger in particular must have `parameters: {}`. Submit the workflow.

conversationContext: Previous build failed with: nodes[0].parameters (invalid_type): Expected object, received null — the Manual Trigger node had null parameters. Fix: ensure all nodes have parameters as a plain object. Workflow name: INS-164 mocked credential guard. Uses mocked slackApi credential placeholder, no real credential needed.

result: Workflow build started (task: build-7ac4d41b). Reply with one short sentence — e.g. name what's being built. Do NOT summarize the plan or list details.


guidance: Fix the workflow code in one batched edit, then call submit-workflow again.

errors: [INVALID_PARAMETER] (Post Slack Message): Node "Post Slack Message": Validation failed: "parameters.select" must be "channel".


content:
/**
 * Slack Node - Version 2.4
 * Discriminator: resource=message, operation=post
 */

interface Credentials {
  slackApi: CredentialReference;
  slackOAuth2Api: CredentialReference;
}

export type SlackV24MessagePostParams = {
  resource: 'message';
  operation: 'post';
  authentication?: 'accessToken' | 'oAuth2' | Expression<string>;
/**
 * Send Message To
 */
    select: 'channel' | 'user' | Expression<string>;
/**
 * The Slack channel to send to
 * @searchListMethod getChannels
 * @displayOptions.show { select: ["channel"] }
 * @default {"mode":"list","value":""}
 */
    channelId?: { __rl: true; mode: 'list' | 'id' | 'name' | 'url'; value: string; cachedResultName?: string };
/**
 * User
 * @searchListMethod getUsers
 * @displayOptions.show { select: ["user"] }
 * @default {"mode":"list","value":""}
 */
    user?: { __rl: true; mode: 'list' | 'id' | 'username'; value: string; cachedResultName?: string };
/**
 * Whether to send a simple text message, or use Slack’s Blocks UI builder for more sophisticated messages that include form fields, sections and more
 * @default text
 */
    messageType?: 'text' | 'block' | 'attachment' | Expression<string>;
/**
 * The message text to post. Supports markdown by default - this can be disabled in "Options".
 * @displayOptions.show { messageType: ["text", "block"] }
 */
    text: string | Expression<string>;
/**
 * Enter the JSON output from Slack's visual Block Kit Builder here. You can then use expressions to add variable content to your blocks. To create blocks, use Slack's Block Kit Builder
 * @hint To create blocks, use Slack's Block Kit Builder
 * @displayOptions.show { messageType: ["block"] }
 */
    blocksUi: string | Expression<string>;
/**
 * Attachments
 * @displayOptions.show { messageType: ["attachment"] }
 * @default {}
 */
    attachments?: Array<{
    /** Required plain-text summary of the attachment
     */
    fallback?: string | Expression<string>;
    /** Text
     */
    text?: string | Expression<string>;
    /** Title
     */
    title?: string | Expression<string>;
    /** Title Link
     */
    title_link?: string | Expression<string>;
    /** Color of the line left of text
     * @default #ff0000
     */
    color?: string | Expression<string>;
    /** Text which appears before the message block
     */
    pretext?: string | Expression<string>;
    /** Name that should appear
     */
    author_name?: string | Expression<string>;
    /** Author Link
     */
    author_link?: string | Expression<string>;
    /** Icon which should appear for the user
     */
    author_icon?: string | Expression<string>;
    /** Image URL
     */
    image_url?: string | Expression<string>;
    /** Thumbnail URL
     */
    thumb_url?: string | Expression<string>;
    /** Text of footer to add
     */
    footer?: string | Expression<string>;
    /** Icon which should appear next to footer
     */
    footer_icon?: string | Expression<string>;
    /** Timestamp of the message to post
     * @default 0
     */
    ts?: number | Expression<number>;
    /** Fields to add to message
     * @default {}
     */
    fields?: {
        /** Item
     */
    item?: Array<{
      /** Title
       */
      title?: string | Expression<string>;
      /** Value
       */
      value?: string | Expression<string>;
      /** Whether items can be displayed next to each other
       * @default true
       */
      short?: boolean | Expression<boolean>;
    }>;
  };
  }>;
/**
 * Other options to set
 * @default {}
 */
    otherOptions?: {
    /** Whether to append a link to this workflow at the end of the message. This is helpful if you have many workflows sending Slack messages.
     * @default true
     */
    includeLinkToWorkflow?: boolean | Expression<boolean>;
    /** Set an image or an emoji as the Profile Photo (avatar) of the bot sending the message. Will not be used if sending message as a user.
     * @default {"imageValues":[{"profilePhotoType":""}]}
     */
    botProfile?: {
        /** Add Bot Profile Photo
     */
    imageValues?: {
      /** Profile Photo Type
       */
      profilePhotoType?: 'image' | 'emoji' | Expression<string>;
      /** Only used if sending message as a bot. Use emoji codes like +1, not an actual emoji like 👍. List of common emoji codes
       * @displayOptions.show { profilePhotoType: ["emoji"] }
       */
      icon_emoji?: string | Expression<string>;
      /** Only used if sending message as a bot
       * @displayOptions.show { profilePhotoType: ["image"] }
       */
      icon_url?: string | Expression<string>;
    };
  };
    /** Whether to turn @users and #channels in message text into clickable links
     * @default false
     */
    link_names?: boolean | Expression<boolean>;
    /** Provide another message's Timestamp value to make this message a reply
     * @default {}
     */
    thread_ts?: {
        /** Reply to a Message
     */
    replyValues?: {
      /** Message timestamps are included in output data of Slack nodes, abbreviated to ts
       */
      thread_ts?: number | Expression<number>;
      /** Whether the reply should be made visible to everyone in the channel or conversation
       * @default false
       */
      reply_broadcast?: boolean | Expression<boolean>;
    };
  };
    /** Whether to use Slack Markdown to format the message
     * @default true
     */
    mrkdwn?: boolean | Expression<boolean>;
    /** Whether to enable unfurling of primarily text-based content
     * @default false
     */
    unfurl_links?: boolean | Expression<boolean>;
    /** Whether to disable unfurling of media content
     * @default true
     */
    unfurl_media?: boolean | Expression<boolean>;
    /** Whether to send a temporary, ephemeral message
     * @displayOptions.show { /select: ["channel"] }
     * @default {}
     */
    ephemeral?: {
        /** Send as Ephemeral Message
     */
    ephemeralValues?: {
      /** User to Send
       * @searchListMethod getUsers
       * @default {"mode":"list","value":""}
       */
      user?: { __rl: true; mode: 'list' | 'id'; value: string; cachedResultName?: string };
      /** Whether to send a temporary, ephemeral message
       * @default true
       */
      ephemeral?: boolean | Expression<boolean>;
    };
  };
    /** Whether to send a temporary, ephemeral message
     * @displayOptions.show { /select: ["user"] }
     * @default true
     */
    ephemeral?: boolean | Expression<boolean>;
    /** The message will be sent from this username (i.e. as if this individual sent the message). Add chat:write.customize scope on Slack API
     * @displayOptions.show { /authentication: ["accessToken"] }
     */
    sendAsUser?: string | Expression<string>;
  };
};

export type SlackV24MessagePostOutput = {
  channel?: string;
  message?: {
    app_id?: string;
    blocks?: Array<{
      block_id?: string;
      elements?: Array<{
        elements?: Array<{
          style?: {
            italic?: boolean;
          };
          text?: string;
          type?: string;
          url?: string;
        }>;
        type?: string;
      }>;
      type?: string;
    }>;
    bot_id?: string;
    bot_profile?: {
      app_id?: string;
      deleted?: boolean;
      icons?: {
        image_36?: string;
        image_48?: string;
        image_72?: string;
      };
      id?: string;
      name?: string;
      team_id?: string;
      updated?: number;
    };
    team?: string;
    text?: string;
    ts?: string;
    type?: string;
    user?: string;
  };
  message_timestamp?: string;
  ok?: boolean;
};

export type SlackV24MessagePostNode = {
  type: 'n8n-nodes-base.slack';
  version: 2.4;
  credentials?: Credentials;
  config: NodeConfig<SlackV24MessagePostParams>;
  output?: Items<SlackV24MessagePostOutput>;
};


warnings: [CREDENTIALS_MOCKED]: Mocked slackApi via pinned data on nodes: Post Slack Message. Add real credentials before publishing.


toolName: verify-built-workflow

preview:
<untrusted_data source="execution-output" label="node:Manual Trigger">
[
  {}
]
</untrusted_data>

preview:
<untrusted_data source="execution-output" label="node:Post Slack Message">
[
  {
    "_mockedCredential": "slackApi"
  }
]
</untrusted_data>