# Nodes

Nodes are the building blocks of MindedJS flows - discrete processing units that handle different aspects of your agent's workflow.

## Common Node Properties

All nodes require these fields:

* `name` (string, required): Unique identifier for the node
* `type` (NodeType, required): The node type (see table below)
* `displayName` (string, required): Human-readable label shown in the editor

## Node Types Overview

| Node Type (`NodeType`)               | Purpose        | Description                              |
| ------------------------------------ | -------------- | ---------------------------------------- |
| [`trigger`](#trigger-nodes)          | Entry Points   | Start flows from various sources         |
| [`promptNode`](#prompt-nodes)        | LLM Processing | Generate responses using language models |
| [`tool`](#tool-nodes)                | Actions        | Execute external functions and APIs      |
| [`junction`](#junction-nodes)        | Flow Control   | Route and organize flow logic            |
| [`jumpToNode`](#jump-to-nodes)       | Flow Control   | Jump to specific nodes or subflows       |
| [`browserTask`](#browser-task-nodes) | Automation     | AI-powered web page interactions         |

## Trigger Nodes

Trigger nodes are entry points that start your flows and initialize them with memory and messages.

### Trigger Nodes Properties

* `type` (NodeType, required): Always `trigger`
* `triggerType` (string, required): The type of trigger to use. See the table below for details.

| `triggerType` | Description                                                     |
| ------------- | --------------------------------------------------------------- |
| `webhook`     | Triggered by HTTP webhook calls                                 |
| `app`         | Triggered by external app events (e.g., Zendesk ticket created) |
| `schedule`    | Triggered on a cron schedule                                    |

#### Webhook Trigger (`webhook`)

Triggered by HTTP requests to the agent's webhook endpoint.

**Properties**:

* `autoTrigger` (boolean, optional): Auto-execute when testing flows in the UI editor
* `defaultPayload` (string, optional): Default JSON payload for testing in the UI editor

```yaml
- type: trigger
  triggerType: webhook
  name: payment-webhook
  displayName: Payment Webhook
  autoTrigger: true
  defaultPayload: '{"orderId": "123"}'
```

#### App Trigger (`app`)

Triggered by external application events.

```yaml
- type: trigger
  triggerType: app
  name: zendesk-ticket-created
  displayName: Zendesk Ticket Created
  appTriggerId: zendesk-new-ticket
```

#### Schedule Trigger (`schedule`)

Triggered on a cron schedule.

**Properties**:

* `cronExpression` (string, required): Cron expression (e.g., `0 9 * * *` for daily at 9 AM)
* `timezone` (string, optional): Timezone for the schedule (defaults to UTC)

```yaml
- type: trigger
  triggerType: schedule
  name: daily-report
  displayName: Daily Report
  cronExpression: '0 9 * * *'
```

### Trigger Implementation

Handle triggers in your agent code:

```ts
import { Agent, AgentEvents } from '@minded-ai/mindedjs';

const agent = new Agent({ /* agent options... */ });

agent.on(AgentEvents.TRIGGER_EVENT, async ({ triggerName, triggerBody, state }) => {
  if (triggerName === 'payment-webhook' && triggerBody.body?.orderId) {
    state.memory.orderId = triggerBody.body.orderId;
    return { isQualified: true };
  }
  
  // Return { isQualified: false } to prevent flow execution
  return { isQualified: false };
});

export default agent;
```

## Prompt Nodes

Prompt nodes process input through LLM to generate intelligent responses or invoke tools. Prompt nodes are commonly used to notify and collect information.

### Use Cases

* Notify the user about the result of a previous node.
* Collect information from the user.
* Invoke (scoped) tools.

### Prompt Nodes Properties

* `type`: (NodeType, required) Always `promptNode`
* `prompt` (string, required): The prompt to be sent to the LLM. The prompt is an instruction for what AI message to generate or a (scoped) tool to invoke. This is not general instruction for what the agent should do (e.g. "wait for x").
* `humanInTheLoop` (boolean, optional): When `true`, pauses execution after this node for human input before continuing. Use this property only if you need to gather an input from the user. Usually combined with a `promptCondition` edge to allow for iterative processing over human input.
* `canStayOnNode` (boolean, optional): When `true`, allows the node to route back to itself for iterative processing. Usually combined with `humanInTheLoop: true` to allow for iteration over human input.
* `llmConfig` (boolean, optional): Used to customize the LLM used by the prompt node. Leave empty to use the default LLM configured.
* `sendAiMessage` (boolean, optional): Default: `true`. When `true` emits `AgentEvents.AI_MESSAGE` event to send the response to the user. When `false`, the AI response is processed internally without sending to the user. Set to `false` for internal calculations, reasoning, or decision-making logic that shouldn't be visible to users.

```yaml
- type: promptNode
  name: generate-order-confirmation
  displayName: Generate Order Confirmation
  prompt: 'Generate Order Confirmation for {memory.customerName}'
  sendAiMessage: true
```

### Handle AI message (`sendAiMessage`)

Prompt nodes usually result in an AI message being sent to the user. Use the `AgentEvents.AI_MESSAGE` event to route the message according to user requirement (e.g., send email, send a Slack message, update Jira ticket, etc.).

```js
agent.on(AgentEvents.AI_MESSAGE, ({ message, state }) => {
  // Send message to Slack channel
  slackChat.postMessage({
    ...options,
    test: message
  });
});;
```

In development mode (playground), the message is automatically shown in the chat regardless of the message handler.

### Context

* Prompt nodes automatically have access to previous nodes' output as context.
* You can inject dynamic values into prompts using placeholders that reference memory, environment variables, tool outputs, and system values.

**Available Placeholders**

* [Memory](#memory-placeholders): `{state.memory.propertyName}` or `{memory.propertyName}`
* [Tool outputs](#toolnode-output-placeholders): `{tools.NodeName.propertyName}`
* [Environment variables](#environment-variable-placeholders): `{env.VARIABLE_NAME}`
* [System values](#system-placeholders): `{system.propertyName}`

#### Memory Placeholders

Access values from the agent's memory state using `{memory.propertyName}`:

```yaml
prompt: 'Send a confirmation email to {memory.customerName} that their order {memory.orderId} has been processed successfully'
```

**Nested objects:**

```yaml
prompt: 'Generate a shipping label for delivery to {memory.customer.address.city}, {memory.customer.address.country} and notify the customer'
```

**Array access:**

```yaml
prompt: 'Create a packing list including {memory.orderItems[0]} and {memory.orderItems[1]} with their quantities'
```

**Complex objects:**

When referencing entire objects or arrays, they will be serialized to JSON:

```yaml
prompt: 'Validate the following order data and check for any inconsistencies: {memory.orderDetails}'
# If orderDetails is {id: "123", total: 99.99}, the prompt interpolated as:
# Validate the following order data and check for any inconsistencies: {"id":"123","total":99.99}
```

#### Tool/Node Output Placeholders

Access output from previous tool or operator nodes using `{tools.NodeName.propertyName}`:

```yaml
# After a tool node named "lookup-customer" returns {email: "user@example.com", tier: "premium"}
prompt: 'Send a personalized welcome email to {tools.lookup-customer.email} with {tools.lookup-customer.tier} tier benefits'
```

**With operator/browser task nodes:**

```yaml
# After an operator node named "scrape-price" with outputSchema field "price"
prompt: 'Compare the scraped price of {tools.scrape-price.price} with our database and alert if there is a significant difference'
```

#### Environment Variable Placeholders

Access environment variables using `{env.VARIABLE_NAME}`:

```yaml
prompt: 'If the user needs help, direct them to contact support at {env.SUPPORT_EMAIL} or call {env.SUPPORT_PHONE}'
```

**Common use cases:**

```yaml
# API endpoints
prompt: 'Fetch the latest order status from {env.API_BASE_URL}/orders and summarize it for the customer'
```

```yaml
# Company information
prompt: 'Draft a professional response thanking the customer for choosing {env.COMPANY_NAME} and offer assistance'
```

#### System Placeholders

Access built-in system values using `{system.propertyName}`:

```yaml
prompt: 'Log this customer inquiry with timestamp {system.currentTime} and respond with an acknowledgment'
# The timestamp will be: 2024-01-15T10:30:00.000Z
```

#### Placeholder Behavior

* **String values**: Inserted directly into the prompt
* **Numbers and booleans**: Converted to strings
* **Objects and arrays**: Serialized to JSON format
* **Undefined values**: If a placeholder references a non-existent property, it returns the original placeholder unchanged (e.g., `{memory.nonexistent}` stays as `{memory.nonexistent}`)
* **Null values**: Rendered as `"null"`

#### Complete Example

```yaml
nodes:
  - type: promptNode
    name: order-confirmation
    displayName: Order Confirmation
    prompt: |
      Order Confirmation for {memory.customerName}
      
      Order Details:
      - Order ID: {memory.orderId}
      - Items: {memory.orderItems}
      - Total: {memory.orderTotal}
      - Customer Tier: {tools.lookup-customer.tier}
      - Shipping to: {memory.shippingAddress.city}
      
      Support: {env.SUPPORT_EMAIL}
      Processed at: {system.currentTime}
```

### Limitations

* Prompt nodes can not save information to memory directly. Rather the user & agent messages are stored in the messages array of the state object. Making user's input available to the next prompt nodes or tools in the form of input schema.
* Image recognition is only supported when a user attaches an image to the message. If you need to extract information from an image, use a tool with agent.llm to process the image. Return the result in the tool response so following prompt nodes can use it.
* By default, prompt nodes send a message to the user. Set `sendAiMessage: false` if you want internal processing without user-facing output.

### Prompt examples

* "Draft a professional email to the merchant requesting verification of the dispute"
* "Ask the user for their contact information (name, email, phone)"

### Common Prompt Patterns

#### Extract Information from User

Use `humanInTheLoop: true` and `canStayOnNode: true` with `promptCondition` edges for iterative information gathering:

```yaml
nodes:
  - type: promptNode
    name: collect-customer-info
    displayName: Collect Customer Information
    prompt: 'Ask the user for their contact information (name, email, phone).'
    humanInTheLoop: true
    canStayOnNode: true

edges:
  - type: promptCondition
    source: collect-customer-info
    target: validate-info
    prompt: 'Has all required information been collected?'
```

#### Notify User

Use standard prompt nodes with `stepForward` edges for one-way notifications:

```yaml
nodes:
  - type: promptNode
    name: send-confirmation
    displayName: Send Confirmation
    prompt: 'Send confirmation: Order {memory.orderId}, Total: {memory.orderTotal}'

edges:
  - type: stepForward
    source: process-order
    target: send-confirmation
```

### Custom LLM Configuration

Provide a custom LLM configuration to the prompt node using the `llmConfig` property with the following fields:

* `name`: (required) name of the LLM to use, must be one of `ChatOpenAI`, `AzureChatOpenAI`, `MindedChatOpenAI`.
* `properties`: (optional) LLM configuration properties

```yaml
nodes:
  - type: promptNode
    name: send-confirmation
    displayName: Send Confirmation
    prompt: 'Send confirmation: Order {memory.orderId}, Total: {memory.orderTotal}'
    llmConfig:
      name: ChatOpenAI
      properties:
        model: gpt-5.2
        temperature: 0
        max_tokens: 500
```

### Internal Processing (No User Message)

To process logic internally without sending a message to the user, set `sendAiMessage: false`:

```yaml
- type: promptNode
  name: calculate-refund-amount
  displayName: Calculate Refund Amount
  prompt: 'Based on the order details: {memory.orderItems}, calculate the appropriate refund amount.'
  sendAiMessage: false
```

Use cases for `sendAiMessage: false`:

* **Internal calculations and reasoning**: Determining refund amounts, calculating discounts, analyzing data
* **Decision-making logic**: Evaluating conditions before taking actions
* **Information extraction**: Processing and structuring data for subsequent nodes
* **Pre-processing**: Preparing inputs for tools or other nodes

The AI response is added to conversation history and available to subsequent nodes, but not sent to the user.

## Tool Nodes

Tool nodes execute functions to perform actions like API calls, database queries, or external integrations.

### Tool Nodes Properties

* `type` (NodeType, required): Always `tool`
* `toolName` (string, required): The name of the registered tool function to execute. Must match a tool defined in your agent's tools configuration.
* `prompt` (string, optional): The prompt to be sent to the LLM to hint how tool parameters should be inferred.
* `parameters` (object, optional): The parameters to pass to the tool function. Tool parameters values are inferred by an LLM during runtime. You can override specific input parameters directly to ensure deterministic values. Parameters support placeholder syntax to inject dynamic values from memory, environment variables, other tool outputs, and system values. See [Context](#context) for more details.

```yaml
- type: tool
  name: lookup-customer-order
  displayName: Lookup Customer Order
  toolName: lookupOrder
  parameters:
    orderId: '{tools.lookup-customer.orderId}'
```

### Tool Implementation

Tools are registered in your agent code. See [Tools](https://docs.minded.com/low-code-editor/tools) for implementation details.

## Junction Nodes

Junction nodes provide flow control without processing, useful for organizing routing logic.

### Basic Junction

```yaml
- type: junction
  name: customer-routing-hub
  displayName: Customer Routing Hub
```

### Routing Example

```yaml
nodes:
  - type: junction
    name: route-customer-request
    displayName: Route Customer Request

edges:
  - source: route-customer-request
    target: vip-support
    type: logicalCondition
    condition: "state.memory.customerTier === 'premium'"
  - source: route-customer-request
    target: standard-support
    type: logicalCondition
    condition: "state.memory.customerTier === 'standard'"
```

## Jump To Nodes

Jump To nodes provide direct navigation to specific nodes, enabling flow transitions and subflow execution.

### Jump To Node Properties

* `type` (NodeType, required): Always `jumpToNode`
* `targetNodeId` (string, required) The `name` of the node to jump to. The target node is resolved across all loaded flows at runtime. If the target node doesn't exist, the flow will error.

### Basic Jump To Node

```yaml
nodes:
  - type: jumpToNode
    name: go-to-order-processing
    displayName: Go To Order Processing
    targetNodeId: process-customer-order
```

### Cross-Flow Navigation

Jump To nodes enable navigation between flows. Target nodes can exist in different flow files, and state is preserved during jumps:

```yaml
# flows/mainFlow.yaml
nodes:
  - type: jumpToNode
    name: go-to-refund-flow
    displayName: Go To Refund Flow
    targetNodeId: refund-processor  # resolves to node in any loaded flow
```

```yaml
# flows/refundFlow.yaml
nodes:
  - type: tool
    name: refund-processor
    displayName: Refund Processor
    toolName: refundOrder
```

## Browser Task Nodes

Browser task nodes allow your agent to interact with web pages using AI-powered automation.

### Browser Task Properties

* `type` (NodeType, required): Always `browserTask`
* `prompt` (string, required): The prompt to be sent to the LLM to instruct the browser task.

### Basic Browser Task

```yaml
- type: browserTask
  name: search-products
  displayName: Search Products
  prompt: 'Go to amazon.com and search for wireless headphones under $100'
```

### Custom Model

Specify which AI model to use (default: `gpt-5.2`):

```yaml
- type: browserTask
  name: complex-task
  displayName: Complex Web Task
  prompt: 'Navigate to the support page and fill out the contact form'
  model: 'gpt-5.2'
```

## Best Practices

* **Use descriptive names**: `technical-support-specialist` not `agent-1`
* **Keep prompts focused**: Define specific roles and context, avoid overly broad prompts
* **Always include `displayName`**: Required for prompt nodes, recommended for all nodes

## Next Steps

* [**Edges**](https://docs.minded.com/low-code-editor/edges) - Connect nodes with intelligent routing
* [**Tools**](https://docs.minded.com/low-code-editor/tools) - Build powerful tool functions
* [**Memory Types**](https://github.com/minded-ai/mindedjs/blob/main/docs/platform/memory.md) - Design effective state management
