---
title: "Add Workflow Node"
method: POST
path: "/v1/workflows/{workflow_id}/nodes"
tags: ["API v1", "Workflows", "Workflow Nodes"]
---

# Add Workflow Node

`POST /v1/workflows/{workflow_id}/nodes`

## Request

- Base URL: `https://api.xpander.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.xpander.ai/v1/workflows/{workflow_id}/nodes`
- Auth: API key in header `x-api-key`

Add a node to a workflow DAG (action, agent, or advanced) and wire its edges. Cycles are rejected.

## Path parameters

- `workflow_id` string, required

## Query parameters

- `deploy` boolean: Deploy the workflow after adding so the change takes effect immediately.

## Request body

- AddWorkflowNodeRequest: Add a node to a workflow DAG. Use `action`/`agent` for the common cases, or `advanced` for full control.
  - `type` 'action' | 'agent' | 'advanced', required: Node kind to add.
  - `name` string, nullable: Node name.
  - `connection_id` string, nullable: Connection id. Required for type=action.
  - `operation_id` string, nullable: Operation catalog id. Required for type=action.
  - `instructions` string, nullable: Instructions for the action/agent node.
  - `agent_id` string, nullable: Agent id. Required for type=agent.
  - `advanced` OrchestrationNodeInput: A node in an orchestration workflow. Represents a single execution unit in an orchestration with control flow, execution strategies, and a specific node type definition. Attributes: type: Type of the node (must match the definition type). id: Unique identifier for the node. Auto-generated if not provided. next_node_ids: List of IDs of the next nodes to execute. name: Human-readable name for the node. description: Detailed description of the node's purpose. condition: Conditional logic for executing this node. retry_strategy: Strategy for retrying failed executions. iterative_strategy: Strategy for iterative execution. stop_strategy: Strategy for stopping the workflow. definition: The actual node implementation (code, classifier, pointer, or wait). input_type: Expected input format. Defaults to Text. input_schema: JSON schema for structured input validation. input_instructions: Instructions to use for structured input. agentic_context_input_instructions: Instructions to use for agentic context injection. agentic_context_output_instructions: Instructions to use for agentic context update.
    - `type` 'custom_function' | 'code' | 'agent' | 'orchestration' | 'classifier' | 'wait' | 'action' | 'guardrail' | 'summarizer' | 'send_to_end' | 'node_pointer' | 'parallel' | 'self_schedule', required: Types of nodes available in an orchestration workflow. Attributes: CustomFunction: Node that executes a custom function. Code: Node that executes arbitrary code. Agent: Node that invokes an AI agent. Orchestration: Node that references another orchestration. Classifier: Node that classifies inputs using LLM. Wait: Node that pauses execution until a condition is met. Action: Node that triggers an action (api). Guardrail: Node that enforces guardrails on inputs using LLM. Summarizer: Node that summarizes or extracts information from inputs using LLM.
    - `id` string
    - `next_node_ids` string[]
    - `name` string, nullable
    - `description` string, nullable
    - `condition` OrchestrationCondition: Condition for controlling orchestration flow. Attributes: type: Type of condition (regex, contains, else, or comparison operators). term: The pattern or string to match against. Used for 'regex' and 'contains' types. group_id: Optional group ID for group-based classifier routing. When set, routing matches by group ID instead of term matching. path: Path to extract value from input data (e.g., "input.client_id" or "client_id"). Used for comparison operators (equal, not_equal, gt, lt, gte, lte, not_empty). value: Value to compare against. Used with comparison operators. Not required for 'not_empty' type.
      - `type` 'regex' | 'contains' | 'else' | 'equal' | 'not_equal' | 'gt' | 'lt' | 'gte' | 'lte' | 'not_empty', required: Types of conditions for orchestration control flow. Attributes: Regex: Condition based on regular expression matching. Contains: Condition based on substring containment. Else: Fallback condition that always matches (executed when no other conditions match). Equal: Condition based on equality comparison (path == value). NotEqual: Condition based on inequality comparison (path != value). GreaterThan: Condition based on greater than comparison (path > value). LessThan: Condition based on less than comparison (path < value). GreaterThanOrEqual: Condition based on greater than or equal comparison (path >= value). LessThanOrEqual: Condition based on less than or equal comparison (path <= value). NotEmpty: Condition that checks if a path value is not empty/null.
      - `term` string, nullable
      - `group_id` string, nullable
      - `path` string, nullable
      - `value` unknown
    - `retry_strategy` OrchestrationRetryStrategy: Strategy for retrying failed orchestration nodes. Attributes: enabled: Whether retry is enabled for this node. max_retries: Maximum number of retry attempts. Defaults to 3.
      - `enabled` boolean, nullable
      - `max_retries` integer, nullable
    - `iterative_strategy` OrchestrationIterativeStrategyInput: Strategy for iteratively executing orchestration nodes. Attributes: enabled: Whether iterative execution is enabled. max_iterations: Maximum number of iterations. Defaults to 3. end_condition: Optional condition to stop iteration early.
      - `enabled` boolean, nullable
      - `max_iterations` integer, nullable
      - `end_condition` OrchestrationCondition: Condition for controlling orchestration flow. Attributes: type: Type of condition (regex, contains, else, or comparison operators). term: The pattern or string to match against. Used for 'regex' and 'contains' types. group_id: Optional group ID for group-based classifier routing. When set, routing matches by group ID instead of term matching. path: Path to extract value from input data (e.g., "input.client_id" or "client_id"). Used for comparison operators (equal, not_equal, gt, lt, gte, lte, not_empty). value: Value to compare against. Used with comparison operators. Not required for 'not_empty' type.
        - `type` 'regex' | 'contains' | 'else' | 'equal' | 'not_equal' | 'gt' | 'lt' | 'gte' | 'lte' | 'not_empty', required: Types of conditions for orchestration control flow. Attributes: Regex: Condition based on regular expression matching. Contains: Condition based on substring containment. Else: Fallback condition that always matches (executed when no other conditions match). Equal: Condition based on equality comparison (path == value). NotEqual: Condition based on inequality comparison (path != value). GreaterThan: Condition based on greater than comparison (path > value). LessThan: Condition based on less than comparison (path < value). GreaterThanOrEqual: Condition based on greater than or equal comparison (path >= value). LessThanOrEqual: Condition based on less than or equal comparison (path <= value). NotEmpty: Condition that checks if a path value is not empty/null.
        - `term` string, nullable
        - `group_id` string, nullable
        - `path` string, nullable
        - `value` unknown
    - `stop_strategy` OrchestrationStopStrategyInput: Strategy for stopping orchestration execution. Attributes: enabled: Whether the stop strategy is enabled. stop_on_failure: Whether to stop the entire orchestration on node failure. stop_on_condition: Optional condition that will stop execution if met.
      - `enabled` boolean, nullable
      - `stop_on_failure` boolean, nullable
      - `stop_on_condition` OrchestrationCondition: Condition for controlling orchestration flow. Attributes: type: Type of condition (regex, contains, else, or comparison operators). term: The pattern or string to match against. Used for 'regex' and 'contains' types. group_id: Optional group ID for group-based classifier routing. When set, routing matches by group ID instead of term matching. path: Path to extract value from input data (e.g., "input.client_id" or "client_id"). Used for comparison operators (equal, not_equal, gt, lt, gte, lte, not_empty). value: Value to compare against. Used with comparison operators. Not required for 'not_empty' type.
        - `type` 'regex' | 'contains' | 'else' | 'equal' | 'not_equal' | 'gt' | 'lt' | 'gte' | 'lte' | 'not_empty', required: Types of conditions for orchestration control flow. Attributes: Regex: Condition based on regular expression matching. Contains: Condition based on substring containment. Else: Fallback condition that always matches (executed when no other conditions match). Equal: Condition based on equality comparison (path == value). NotEqual: Condition based on inequality comparison (path != value). GreaterThan: Condition based on greater than comparison (path > value). LessThan: Condition based on less than comparison (path < value). GreaterThanOrEqual: Condition based on greater than or equal comparison (path >= value). LessThanOrEqual: Condition based on less than or equal comparison (path <= value). NotEmpty: Condition that checks if a path value is not empty/null.
        - `term` string, nullable
        - `group_id` string, nullable
        - `path` string, nullable
        - `value` unknown
    - `definition` union, required
      - OrchestrationCodeNode: Node that executes arbitrary code. Attributes: code: The code string to execute.
        - `code` string, required
      - OrchestrationClassifierNodeInput: Node that uses LLM to classify inputs into groups. Attributes: groups: List of classification groups to evaluate against. output_type: Expected output format. Defaults to Text. output_schema: JSON schema for structured output validation. instructions: Classification or transformation instructions for the LLM. examples: Example inputs/outputs to guide the LLM behavior. settings: LLM configuration settings.
        - `groups` ClassificationGroup[], required
          - `id` string
          - `name` string, required
          - `evaluation_criteria` string, required
          - `auto_extract_relevant_data` boolean, nullable
          - `data_extraction_keys` string[], nullable
        - `output_type` 'text' | 'markdown' | 'json' | 'voice'
        - `output_schema` object, nullable
        - `instructions` string, nullable
        - `examples` string[], nullable
        - `settings` OrchestrationClassifierNodeLLMSettings, required: LLM configuration for classifier nodes. Attributes: model_provider: The LLM provider to use. Defaults to AmazonBedrock. model_name: Specific model identifier. Defaults to "global.anthropic.claude-opus-5-5". llm_credentials_key: Key identifier for stored credentials. llm_credentials_key_type: Type of credential key storage. Defaults to XPander. llm_credentials: Direct credential object if not using stored credentials. llm_api_base: Alternative API Base for the LLM. llm_extra_headers: Extra headers to be set to LLM Requests.
          - `model_provider` 'openai' | 'nim' | 'amazon_bedrock' | 'azure_ai_foundary' | 'huggingFace' | 'friendlyAI' | 'anthropic' | 'gemini' | 'fireworks' | 'google_ai_studio' | 'helicone' | 'bytedance' | 'tzafon_lightcone' | 'cerebras' | 'open_router' | 'nebius' | 'cloudflare_ai_gw' | 'z_ai'
          - `model_name` string, nullable
          - `llm_credentials_key` string, nullable
          - `llm_credentials_key_type` 'xpander' | 'custom'
          - `llm_credentials` LLMCredentials
            - `name` string, required
            - `description` string, nullable
            - `value` string, required
          - `llm_api_base` string, nullable
          - `llm_extra_headers` object, nullable
      - OrchestrationPointerNode: Node that references an external asset (agent, function, or orchestration). Attributes: asset_id: Unique identifier of the asset to execute. type: Type of asset being referenced. output_type: Expected output format. Defaults to Text. output_schema: JSON schema for structured output validation. instructions: Optional instructions for the pointer node (Action only). instructions_mode: Mode to use for pointer node, specifically for agent nodes. ignore_response: Should ignore the node result and proceed with previous result?. persist_thread_id: Should persist the thread in agent nodes? default (True). schema_override: Optional schema override with permanentValue fields for fixed values.
        - `asset_id` string, required
        - `type` 'agent' | 'custom_function' | 'orchestration' | 'action', required
        - `output_type` 'text' | 'markdown' | 'json' | 'voice'
        - `output_schema` object, nullable
        - `instructions` string, nullable
        - `instructions_mode` 'replace' | 'append': Modes for instruction usage in pointer node. Attributes: Replace: Replaces the traget asset instructions. Append: Appends to the traget asset instructions.
        - `ignore_response` boolean, nullable
        - `persist_thread_id` boolean, nullable
        - `schema_override` SchemaOverride: Schema override for workflow action nodes. Allows setting permanent (fixed) values for tool input properties. Fields with permanentValue will be removed from the schema sent to the LLM and the permanent values will be applied to the payload before execution. Attributes: input: Input schema with permanentValue fields to override LLM-generated values.
          - `input` object, nullable
      - OrchestrationWaitNodeInput: Node that pauses execution until an external event occurs. Attributes: type: Type of wait event (webhook or human-in-the-loop). definition: Notification configuration for triggering continuation.
        - `type` 'webhook' | 'hitl', required
        - `definition` union, required
          - EmailNotificationSettings: Configuration for email notifications. Attributes: to: List of recipient email addresses.
            - `subject` string, nullable
            - `body` string, nullable
            - `approve_button_text` string, nullable
            - `deny_button_text` string, nullable
            - `logo_url` string, nullable
            - `to` string[], required
          - SlackNotificationSettings: Configuration for Slack notifications. Attributes: channels: List of Slack channel IDs or names to post to. connection_id: connector_organization id of a connected Slack workspace. When set and `credentials.access_token` is absent, the delivery path resolves the token server-side from the connection (the client never persists the token). credentials: Slack API authentication credentials. Optional — defaults to empty so a connection_id-only target parses; the token is resolved at send time.
            - `subject` string, nullable
            - `body` string, nullable
            - `approve_button_text` string, nullable
            - `deny_button_text` string, nullable
            - `logo_url` string, nullable
            - `channels` string[], required
            - `connection_id` string, nullable
            - `credentials` SlackCredentials: Slack API authentication credentials. Attributes: authed_user_id: Authenticated user's Slack ID. access_token: OAuth access token for API calls. client_id: Slack app client ID. client_secret: Slack app client secret. verification_token: Token for verifying requests from Slack. signing_secret: Secret for validating webhook signatures. app_configuration_token: Token for app configuration. app_configuration_refresh_token: Refresh token for app configuration.
              - …
          - WebhookNotificationSettings: Configuration for webhook notifications. Attributes: url: Target webhook URL to POST notification data. headers: Optional HTTP headers to include in the webhook request.
            - `subject` string, nullable
            - `body` string, nullable
            - `approve_button_text` string, nullable
            - `deny_button_text` string, nullable
            - `logo_url` string, nullable
            - `url` string, required
            - `headers` object, nullable
      - OrchestrationGuardrailNodeInput: Node that uses LLM to evaluate input against pass/fail criteria. This node works like a classifier with exactly 2 groups: "pass" and "fail". The user defines evaluation_criteria for each group. Routing behavior: - If guardrail passes: routes to downstream node with condition group_id="pass" - If guardrail fails: routes to downstream node with condition group_id="fail" - If no fail route exists: falls back to end nodes (end-summarizer or end-classifier) - A pass route is REQUIRED; fail route is optional. Attributes: groups: List of 2 ClassificationGroup objects with IDs "pass" and "fail". Each group has evaluation_criteria defined by the user. examples: Example inputs/outputs to guide the LLM behavior. settings: LLM configuration settings.
        - `groups` ClassificationGroup[], required
          - `id` string
          - `name` string, required
          - `evaluation_criteria` string, required
          - `auto_extract_relevant_data` boolean, nullable
          - `data_extraction_keys` string[], nullable
        - `examples` string[], nullable
        - `settings` OrchestrationClassifierNodeLLMSettings, required: LLM configuration for classifier nodes. Attributes: model_provider: The LLM provider to use. Defaults to AmazonBedrock. model_name: Specific model identifier. Defaults to "global.anthropic.claude-opus-5-5". llm_credentials_key: Key identifier for stored credentials. llm_credentials_key_type: Type of credential key storage. Defaults to XPander. llm_credentials: Direct credential object if not using stored credentials. llm_api_base: Alternative API Base for the LLM. llm_extra_headers: Extra headers to be set to LLM Requests.
          - `model_provider` 'openai' | 'nim' | 'amazon_bedrock' | 'azure_ai_foundary' | 'huggingFace' | 'friendlyAI' | 'anthropic' | 'gemini' | 'fireworks' | 'google_ai_studio' | 'helicone' | 'bytedance' | 'tzafon_lightcone' | 'cerebras' | 'open_router' | 'nebius' | 'cloudflare_ai_gw' | 'z_ai'
          - `model_name` string, nullable
          - `llm_credentials_key` string, nullable
          - `llm_credentials_key_type` 'xpander' | 'custom'
          - `llm_credentials` LLMCredentials
            - `name` string, required
            - `description` string, nullable
            - `value` string, required
          - `llm_api_base` string, nullable
          - `llm_extra_headers` object, nullable
      - OrchestrationSummarizerNodeInput: Node that processes large payloads and answers specific questions. This node uses an LLM to summarize or extract information from large inputs. Attributes: instructions: Summarization or question-answering instructions for the LLM. examples: Example inputs/outputs to guide the LLM behavior. settings: LLM configuration settings.
        - `instructions` string, required
        - `examples` string[], nullable
        - `settings` OrchestrationClassifierNodeLLMSettings, required: LLM configuration for classifier nodes. Attributes: model_provider: The LLM provider to use. Defaults to AmazonBedrock. model_name: Specific model identifier. Defaults to "global.anthropic.claude-opus-5-5". llm_credentials_key: Key identifier for stored credentials. llm_credentials_key_type: Type of credential key storage. Defaults to XPander. llm_credentials: Direct credential object if not using stored credentials. llm_api_base: Alternative API Base for the LLM. llm_extra_headers: Extra headers to be set to LLM Requests.
          - `model_provider` 'openai' | 'nim' | 'amazon_bedrock' | 'azure_ai_foundary' | 'huggingFace' | 'friendlyAI' | 'anthropic' | 'gemini' | 'fireworks' | 'google_ai_studio' | 'helicone' | 'bytedance' | 'tzafon_lightcone' | 'cerebras' | 'open_router' | 'nebius' | 'cloudflare_ai_gw' | 'z_ai'
          - `model_name` string, nullable
          - `llm_credentials_key` string, nullable
          - `llm_credentials_key_type` 'xpander' | 'custom'
          - `llm_credentials` LLMCredentials
            - `name` string, required
            - `description` string, nullable
            - `value` string, required
          - `llm_api_base` string, nullable
          - `llm_extra_headers` object, nullable
      - OrchestrationSendToEndNode: Node that routes execution to end nodes or finishes the workflow. When triggered, this node will: 1. Route to end nodes (end-summarizer, end-classifier) if they exist 2. Finish workflow execution immediately if no end nodes exist Attributes: message: Optional message or reason for finishing the workflow.
        - `message` string, nullable
      - OrchestrationSelfScheduleNode: Node that pauses the workflow and schedules itself to resume at a later time. At runtime the worker's self-schedule executor: 1. LLM-parses ``when`` (free-text like "in 1 hour", "next Monday 9am") into an absolute ISO-8601 ``run_at`` using the current datetime / user timezone. 2. Creates a row in ``ai_agents_self_schedules`` with the current ``task_id`` and ``workflow_next_node = target_node_id``. 3. Pauses the task. When APScheduler fires the row, the same task is re-invoked with ``payload_extension={"workflow_next_node": target_node_id}`` and the worker resumes execution starting from the target node, re-running target + its forward cone and skipping everything outside that cone. ``target_node_id`` may point to ANY node in the orchestration (forward, backward, or sibling). Backward jumps are bounded by ``max_reschedules`` so loops cannot run away. Attributes: when: Free-text schedule expression, parsed by the worker via an LLM. target_node_id: The id of the node to resume at. Must exist in the orchestration; no topological constraint. prompt: Optional instruction appended to the upstream node's result before being sent as the scheduled run's prompt. If both the upstream result and this prompt are empty, the node fails rather than creating an empty row. max_reschedules: Maximum number of times this node may fire during a single task lifecycle. Once reached, the executor falls through and the graph proceeds via ``next_node_ids``. Defaults to 1.
        - `when` string, required
        - `target_node_id` string, required
        - `prompt` string, nullable
        - `max_reschedules` integer
      - OrchestrationNodePointerDefinition: Definition for a NodePointer node that acts as a graph-position jump. A NodePointer jumps execution to another node's position in the graph. At resolution time, the pointer adopts the source node's definition, type, AND next_node_ids — so after executing the source's logic, the flow continues to the source's original downstream targets. The pointer keeps its own id, name, condition, and strategies. Attributes: source_node_id: ID of the node to jump to.
        - `source_node_id` string, required
      - OrchestrationParallelNodeInput: Node that executes multiple child nodes in parallel. All child nodes receive the same input (the output of the preceding node). When all child nodes complete, their results are combined: - JSON outputs are merged into a single JSON object keyed by node name. - String outputs are concatenated with node name headers. Attributes: nodes: List of child OrchestrationNode objects to execute in parallel. output_type: Expected output format for the combined result. Defaults to Text. output_schema: JSON schema for structured output validation of the combined result. output_instructions: Instructions for transforming the combined output into the schema.
        - `nodes` OrchestrationNodeInput[], required
        - `output_type` 'text' | 'markdown' | 'json' | 'voice'
        - `output_schema` object, nullable
        - `output_instructions` string, nullable
    - `input_type` 'text' | 'markdown' | 'json' | 'voice'
    - `input_schema` object, nullable
    - `input_instructions` string, nullable
    - `agentic_context_input_instructions` string, nullable
    - `agentic_context_output_instructions` string, nullable
    - `return_this` boolean, nullable
  - `after_node_ids` string[], nullable: Append the new node id to the next_node_ids of these existing nodes.
  - `next_node_ids` string[], nullable: Ids of nodes to run after the new node.

## Response `200`

Successful Response

- WorkflowNodeView[]
  - `id` string, required: Node id (use to update/remove the node).
  - `type` string, required: Node type (action, agent, classifier, ...).
  - `name` string, nullable: Node name.
  - `next_node_ids` string[]: Ids of nodes that run after this one.
  - `asset_id` string, nullable: Referenced asset id for action/agent nodes.
  - `connection_id` string, nullable: Connection id parsed from an action node's asset_id.
  - `operation_id` string, nullable: Operation catalog id parsed from an action node's asset_id.
  - `target_agent_id` string, nullable: Agent id for agent nodes.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/xpander/apis/xpander-ai-api-service.md) - [All operations](https://skmtc.dev/xpander/apis/xpander-ai-api-service/llms.txt) - [OpenAPI document](https://skmtc.dev/xpander/apis/xpander-ai-api-service/revisions/725c0066d5df?raw)
