---
schema_version: "1"
id: c99900a612845346d48cd17a482535172e03b67eb8e0e29217cb3633d8dc6241
title: Agent Script Reference
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/agent-network/latest/af-agent-script-reference.md
canonical_url: https://docs.mulesoft.com/agent-network/latest/af-agent-script-reference
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 1451888f2658f1d4acc9fefdd2e362010052746db494b5eef34a4b89507df7b4
description: MuleSoft Documentation Site
release: "2.0"
latest: true
---
---
product: Building Agent Networks
version: 2.0
is-latest-version: true
---

# Agent Script Reference

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

After you configure the assets and other elements of your agent network project, you build the rest
of the workflow using Agent Script. Agent Script enables you to build predictable, context-aware
agent workflows that don’t rely solely on interpretation by an LLM.

- [Agent Script Structure](#agent-script-structure)

- [Node Types](#node-types)

- [A2A Namespace Functions](#a2a-namespace-functions)

- [Built-in Functions](#built-in-functions)

- [Node Outputs](#node-outputs)

- [Node Expressions and References](#node-expressions-and-references)

## Agent Script Structure

The following sections explain settings and configurations specific to MuleSoft agent network
projects. To learn more about Agent Script, see the
[Agent Script documentation](https://developer.salesforce.com/docs/ai/agentforce/guide/agent-script.html).

### Dialect Referencing and Versioning

Agent Script files contain a header specifying the dialect and a version binding. SEMVER major and
minor are used for fixing to a specific dialect version.

The dialect header specifies that the script is strictly bound to a specific version or later of the
AGENTFABRIC dialect. Deploying an agent to a runtime that doesn’t support this version results in an
error.

- Using major.minor (for example, `AGENTFABRIC=1.1`) binds to version 1.1 or later

- Using major only (for example, `AGENTFABRIC=1`) references the latest version within that major
  version

**Example**

```yaml
# @dialect: AGENTFABRIC=1.0
```

### System Section

This section defines the `instructions` attribute, which acts as a default system prompt used
whenever an agentic node doesn’t define its own `system.instructions`.

**Example**

```yaml
system:
  instructions: "You are the onboarding agent"
```

The system section has these parameters.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>instructions</code></p></td><td><p>Default system prompt used when an agentic node doesn’t define its own <code>system.instructions</code>.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr></tbody></table>

### Agent Config Section

The config section is the standard Agent Script config section, with the addition of the optional
`default_llm` field. This section defines metadata and default settings for the agent.

**Example**

```yaml
config:
  agent_name: "employee-onboarding"
  label: "Employee Onboarding Agent"
  description: "An Agent that performs employee onboarding"
```

The config section has these parameters.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>agent_name</code></p></td><td><p>The name identifier for the agent.</p></td><td><p>String</p></td><td><p>-</p></td></tr><tr><td><p><code>label</code></p></td><td><p>A human-readable display name for the agent.</p></td><td><p>String</p></td><td><p>-</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A description of what the agent does.</p></td><td><p>String</p></td><td><p>-</p></td></tr><tr><td><p><code>default_llm</code></p></td><td><p>Specifies a default LLM to be used on all agentic nodes that don’t specify otherwise.</p></td><td><p>@llm reference See <a href="#llm-section">LLM</a></p></td><td><p>No</p></td></tr></tbody></table>

### LLM Section

The `llm` element is where you define the LLMs to use for reasoning and generation. Each `target`
must use the `llm://` URI scheme so the runtime binds to the correct governed connection.

**Example**

```yaml
llm:
    open-api-llm:
     target: "llm://open_ai_connection"
     kind: "OpenAI"
     model: "gpt5-mini"
     reasoning_effort: "LOW"
   gemini-llm:
     target: "llm://gemini_connection"
     kind: "Gemini"
     model: "gemini-3-flash-preview"
     thinking_level: "HIGH"
     top_p: 0.3
```

#### LLM Configuration: OpenAI

The OpenAI configuration has these properties.

> [!NOTE] Bedrock OpenAI uses the `openai.` prefix for model names (for example, `openai.gpt-5.5`),
> which differs from the model names used with OpenAI and Azure OpenAI.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>target</code></p></td><td><p>Governed LLM connection as a URI; must use the <code>llm://</code> scheme</p></td><td><p>URI (<code>llm://…​</code>)</p></td><td><p>Yes</p></td></tr><tr><td><p><code>kind</code></p></td><td><p>Discriminator for the LLM provider; selects which provider-specific attributes apply</p></td><td><p>String, <code>OpenAI</code></p></td><td><p>Yes</p></td></tr><tr><td><p><code>model</code></p></td><td><p>The name of the model to use</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>reasoning_effort</code></p></td><td><p>Constrains effort on reasoning for reasoning models. gpt-5.1 defaults to <code>NONE</code>; previous ones default to <code>MEDIUM</code>.</p></td><td><p>enum['NONE', 'MINIMAL', 'LOW', 'MEDIUM', 'HIGH']</p></td><td><p>No</p></td></tr><tr><td><p><code>temperature</code></p></td><td><p>Controls randomness in the output</p></td><td><p>number</p></td><td><p>No</p></td></tr><tr><td><p><code>top_p</code></p></td><td><p>Nucleus sampling parameter</p></td><td><p>number</p></td><td><p>No</p></td></tr><tr><td><p><code>top_logprobs</code></p></td><td><p>Number of most likely tokens to return at each position</p></td><td><p>integer</p></td><td><p>No</p></td></tr><tr><td><p><code>max_output_tokens</code></p></td><td><p>Maximum number of tokens to generate</p></td><td><p>integer</p></td><td><p>No</p></td></tr></tbody></table>

#### LLM Configuration: Gemini

The Gemini configuration has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>target</code></p></td><td><p>Governed LLM connection as a URI; must use the <code>llm://</code> scheme</p></td><td><p>URI (<code>llm://…​</code>)</p></td><td><p>Yes</p></td></tr><tr><td><p><code>kind</code></p></td><td><p>Discriminator for the LLM provider; selects which provider-specific attributes apply</p></td><td><p>String, <code>Gemini</code></p></td><td><p>Yes</p></td></tr><tr><td><p><code>model</code></p></td><td><p>The name of the model to use</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>thinking_level</code></p></td><td><p>The level of thoughts tokens that the model should generate</p></td><td><p>Enum['LOW', 'HIGH']</p></td><td><p>No</p></td></tr><tr><td><p><code>thinking_budget</code></p></td><td><p>Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent</p></td><td><p>Number</p></td><td><p>No</p></td></tr><tr><td><p><code>temperature</code></p></td><td><p>Controls the degree of randomness in token selection. Lower temperatures are good for prompts that require a less open-ended or creative response, while higher temperatures can lead to more diverse or creative results</p></td><td><p>Number</p></td><td><p>No</p></td></tr><tr><td><p><code>top_p</code></p></td><td><p>Tokens are selected from the most to least probable until the sum of their probabilities equals this value. Use a lower value for less random responses and a higher value for more random responses</p></td><td><p>Number</p></td><td><p>No</p></td></tr><tr><td><p><code>response_logprobs</code></p></td><td><p>Whether to return the log probabilities of the tokens that were chosen by the model at each step</p></td><td><p>Boolean</p></td><td><p>No</p></td></tr><tr><td><p><code>max_output_tokens</code></p></td><td><p>Maximum number of tokens that can be generated in the response</p></td><td><p>Integer</p></td><td><p>No</p></td></tr></tbody></table>

### Action Definitions

You define A2A and MCP actions in Agent Script under the top-level `actions` block. Each action
`target` uses a URI whose scheme is the underlying protocol (for example `a2a://` or `mcp://`), so
the runtime can route the connection correctly.

#### A2A Actions

A2A actions execute the `message/send` A2A method and do not specify inputs or outputs.

**Example**

```yaml
actions:
  hr_agent:
    target: "a2a://hr_agent_connection"
    kind: "a2a:send_message"
```

A2A actions have these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>target</code></p></td><td><p>Governed A2A connection as a URI; must use the <code>a2a://</code> scheme</p></td><td><p>URI (<code>a2a://…​</code>)</p></td><td><p>Yes</p></td></tr><tr><td><p><code>kind</code></p></td><td><p>Indicates that this executes the message/send A2A method.</p></td><td><p>"a2a:send_message"</p></td><td><p>Yes</p></td></tr></tbody></table>

#### MCP Actions

MCP actions invoke Model Context Protocol actions with optional input binding.

**Example**

```yaml
actions:
  send_slack_message:
    target: "mcp://slack_mcp_connection"
    kind: "mcp:tool"
    tool_name: "send-message"
    inputs:
      channel: string = "my-default-channel"
      message: string
```

MCP actions have these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>target</code></p></td><td><p>Governed MCP connection as a URI; must use the <code>mcp://</code> scheme</p></td><td><p>URI (<code>mcp://…​</code>)</p></td><td><p>Yes</p></td></tr><tr><td><p><code>kind</code></p></td><td><p>Constant indicating that this invokes an MCP tool</p></td><td><p>"mcp:tool"</p></td><td><p>Yes</p></td></tr><tr><td><p><code>tool_name</code></p></td><td><p>The name of the tool to call</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>inputs</code></p></td><td><p>Define bindable arguments. Input arguments provided are not exhaustive. The tool will auto-discover additional arguments and consider them in slot filling mode.</p></td><td><p>Object</p></td><td><p>No</p></td></tr></tbody></table>

### A2A Trigger

Triggers reference one of the interfaces defined for a broker in the agent network. Each broker must
have one—​and only one—​trigger per each interface declared in its agent network.

The A2A trigger reacts to send/message methods and automatically manages the task history, context
ID and task IDs. The trigger also responds to various A2A protocol methods.

> [!NOTE] Agent network only supports triggers using JSON-RPC or HTTP JSON transport.

- [Get Task](https://a2a-protocol.org/latest/specification/#313-get-task)

- [List Tasks](https://a2a-protocol.org/latest/specification/#314-list-tasks)

- [Cancel Task](https://a2a-protocol.org/latest/specification/#315-cancel-task)

- [Subscribe to Task](https://a2a-protocol.org/latest/specification/#316-subscribe-to-task)

- [Get Extended Agent Card](https://a2a-protocol.org/latest/specification/#3111-get-extended-agent-card)

**Example**

```yaml
trigger employeeOnboardingTrigger:
  kind: "a2a"
  target: "brokers://employee-onboarding/a2a"
  on_message: -> transition to @orchestrator.hrSystemOnboard
```

The A2A trigger has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>kind</code></p></td><td><p>Value that indicates this is an A2A trigger.</p></td><td><p><code>"a2a"</code></p></td><td><p>Yes</p></td></tr><tr><td><p><code>target</code></p></td><td><p>Broker interface entry point. Must use the <code>brokers://</code> URI form: <code>brokers://&lt;brokerName&gt;/&lt;interfaceName&gt;</code></p></td><td><p>URI (<code>brokers://…​</code>)</p></td><td><p>Yes</p></td></tr><tr><td><p><code>on_message</code></p></td><td><p>Procedure that executes when the A2A interface receives a new <code>message/send</code> request. Must define a transition to the workflow’s initial node.</p></td><td><p>Procedure</p></td><td><p>Yes</p></td></tr></tbody></table>

## Node Types

Agent network and Agent Script support these node types.

### Choosing the Right Node Type

Use this table to decide which node type fits your use case.

<table><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th></th><th>Subagent</th><th>Orchestrator</th><th>Generator</th><th>Executor</th></tr></thead><tbody><tr><td><p><strong>Uses an LLM</strong></p></td><td><p>Yes (reasoning loop)</p></td><td><p>Yes (reasoning loop)</p></td><td><p>Yes (single call)</p></td><td><p>No</p></td></tr><tr><td><p><strong>Calls actions (A2A/MCP)</strong></p></td><td><p>Yes—​LLM chooses when and how</p></td><td><p>Yes—​LLM coordinates multiple agents/tools</p></td><td><p>No</p></td><td><p>Yes—​deterministic, fully-bound arguments</p></td></tr><tr><td><p><strong>Number of LLM iterations</strong></p></td><td><p>Multiple (configurable loop)</p></td><td><p>Multiple (configurable loop)</p></td><td><p>Exactly one</p></td><td><p>Zero</p></td></tr><tr><td><p><strong>Slot filling (<code>…​</code>)</strong></p></td><td><p>Yes</p></td><td><p>Yes</p></td><td><p>No</p></td><td><p>No</p></td></tr><tr><td><p><strong>Structured output schema</strong></p></td><td><p>Yes</p></td><td><p>Yes</p></td><td><p>Yes</p></td><td><p>No</p></td></tr><tr><td><p><strong>Best for</strong></p></td><td><p>Single-task reasoning: classification, extraction, semantic routing, human-in-the-loop decisions</p></td><td><p>Multi-agent coordination: delegating to several agents/tools to achieve a complex goal</p></td><td><p>One-shot text generation: summaries, formatting, templated responses</p></td><td><p>Deterministic execution: calling actions with known arguments, setting variables, no LLM judgment needed</p></td></tr></tbody></table>

#### Orchestrator vs. Subagent: When to Use Which

Both the orchestrator and subagent nodes run an LLM reasoning loop with access to actions. These are
the key differences.

- **Orchestrator** is optimized for workflows where the LLM must coordinate multiple external agents
  and tools to achieve a goal. The LLM decides which agents to call, in what order, and how to
  combine their results. Use it when the node needs access to two or more actions and the sequencing
  between them requires judgment.

- **Subagent** is a general-purpose reasoning node ideal for single-task work: classifying input,
  extracting structured data, making a routing decision, or interacting with one tool. It also
  supports human-in-the-loop patterns where the LLM can request clarification.

> [!TIP] If the node coordinates multiple agents or tools toward a shared goal, use `orchestrator`.
> If it reasons about a single task (even if it uses one action), use `subagent`.

### Subagent Node

This node defines a generic agent loop node, made of a prompt and a set of actions. Because it can
use actions and supports human-in-the-loop flows, this node is ideal for implementing patterns like
classification, semantic routing, or LLM reasoning.

**Example**

```yaml
- subagent profile-extractor:
     description: "Extracts structured user profile data from text"
     reasoning:
       instructions: -> Extract the following information from the user's message: {!@request.payload.message.parts[0].text}
       outputs:
         properties:
           name:
             type: "string"
             description: "Full name of the person"
             minLength: 1
           email:
             type: "string"
             description: "Email address"
             pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
           age:
             type: "integer"
             description: "Person's age"
             minimum: 0
             maximum: 150
           preferences:
             type: "object"
             description: "User preferences"
             properties:
               newsletter:
                 type: "boolean"
                 description: "Whether user wants newsletter"
                 default: "false"
               category:
                 type: "string"
                 description: "Preferred category"
                 enum:
                   - "tech"
                   - "business"
                   - "sports"
           tags:
             type: "array"
             description: "Interest tags"
             items:
               type: "string"
             minItems: 1
             maxItems: 10
       max_number_of_loops: 5
       max_consecutive_errors: 5
       task_timeout_secs: 30
     on_exit: -> transition to @orchestrator.process_profile
```

The subagent node has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>on_exit</code></p></td><td><p>A procedure that executes when the node execution finishes. If <code>on_exit</code> is not defined, the graph ends when the agentic node loop ends.</p></td><td><p>Procedure, but only <code>transition_to</code> statements are allowed.</p></td><td><p>No</p></td></tr><tr><td><p><code>llm</code></p></td><td><p>Overrides the default LLM setting</p></td><td><p>@llm reference See <a href="#llm-section">LLM Section</a></p></td><td><p>No</p></td></tr><tr><td><p><code>system.instructions</code></p></td><td><p>Overrides the global <code>system.instructions</code> at the file root level</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.instructions</code></p></td><td><p>Session-specific query or instructions for this particular node, typically containing user provided or user related context</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>reasoning.actions</code></p></td><td><p>The available actions</p></td><td><p>Array[actions]</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.outputs</code></p></td><td><p>Schema definition describing the expected structure of the agent’s output</p></td><td><p>Outputs See <a href="#node-outputs">Node Outputs</a></p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.max_number_of_loops</code></p></td><td><p>The maximum number of loops an execution can take. Useful for keeping the execution from running too long and consuming too many tokens. Default: 25</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.max_consecutive_errors</code></p></td><td><p>The maximum number of consecutive errors allowed during execution. Useful for keeping the node from running too long and consuming too many tokens.</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.task_timeout_secs</code></p></td><td><p>A timeout (in seconds) for the total node execution.</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>outputs</code></p></td><td><p>A schema definition for the agentic output.</p></td><td><p>Object See <a href="#node-outputs">Node Outputs</a></p></td><td><p>No</p></td></tr></tbody></table>

### Orchestrator Node

The orchestrator node is a specialization of the subagent node used for orchestrating multiple
agents and MCP servers to achieve a specified goal. It is optimized for multi-agent orchestration.
Use this node type for workflows that need to call multiple external agents or actions to achieve a
goal.

**Example**

```yaml
orchestrator flight-booking-agent:
     description: books flights by looking for the best offer across approved partners
     system:
       instructions: "You are a flight booking agent. The process for flight booking is: 1. Ask the user for a destination and travel dates and present them with matching alternatives using available actions. 2. Allow the user to change or refine the search. 3. Once the user selects a flight, book it using the concur agent tool."
     reasoning:
       instructions: -> @request.payload.message.parts[0].text
       actions:
         search-flight: @actions.search-flight with companyId = @variables.companyId
         get-flight-info: @actions.get-flight-info
         concur: @actions.concur-agent with http_headers = {"Authorization": @request.headers["Authorization"]}
       max_number_of_loops: 10
       max_consecutive_errors: 10
       task_timeout_secs: 60
     outputs:
       properties:
         flightNumber:
           type: "string"
           description: "The flight identification number"
         airline:
           type: "string"
           description: "The airline name"
     on_exit: -> transition to @executor.send_summary
```

The orchestrator node has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>on_exit</code></p></td><td><p>A procedure that executes when the node execution finishes. If <code>on_exit</code> is not defined, the graph ends when the agentic node loop ends.</p></td><td><p>Procedure, but only <code>transition_to</code> statements are allowed.</p></td><td><p>No</p></td></tr><tr><td><p><code>llm</code></p></td><td><p>Overrides the default LLM setting</p></td><td><p>@llm reference See <a href="#llm-section">LLM Section</a></p></td><td><p>No</p></td></tr><tr><td><p><code>system.instructions</code></p></td><td><p>Overrides the global <code>system.instructions</code> at the file root level</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.instructions</code></p></td><td><p>Session-specific query or instructions for this particular node, typically containing user provided or user related context</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>reasoning.actions</code></p></td><td><p>The available actions</p></td><td><p>Array[actions]</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.outputs</code></p></td><td><p>Schema definition describing the expected structure of the agent’s output</p></td><td><p>Outputs See <a href="#node-outputs">Node Outputs</a></p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.max_number_of_loops</code></p></td><td><p>The maximum number of loops an execution can take. Useful for keeping the execution from running too long and consuming too many tokens. Default: 25</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.max_consecutive_errors</code></p></td><td><p>The maximum number of consecutive errors allowed during execution. Useful for keeping the node from running too long and consuming too many tokens.</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>reasoning.task_timeout_secs</code></p></td><td><p>A timeout (in seconds) for the total node execution.</p></td><td><p>Integer</p></td><td><p>No</p></td></tr><tr><td><p><code>outputs</code></p></td><td><p>A schema definition for the agentic output.</p></td><td><p>Object See <a href="#node-outputs">Node Outputs</a></p></td><td><p>No</p></td></tr></tbody></table>

### Generator Node

The generator node calls an LLM to generate text. It is not an agent loop, and it does not support
human-in-the-loop learning or other actions. It performs exactly one LLM call. Use this node for
summarization, formatting, or templated text generation.

**Example**

```yaml
generator summarize-report:
  description: "Generate a one-paragraph summary of the report."
  prompt: "Summarize the following in one paragraph: {!@variables.report}"
  on_exit: ->        transition to ...
```

The generator node has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>on_exit</code></p></td><td><p>A procedure that executes when the node execution finishes. If <code>on_exit</code> is not defined, the graph ends when the agentic node ends.</p></td><td><p>Procedure, but only <code>transition_to</code> statements are allowed.</p></td><td><p>No</p></td></tr><tr><td><p><code>llm</code></p></td><td><p>A reference to the LLM connection.</p></td><td><p>@llm reference See <a href="#llm-section">LLM Section</a></p></td><td><p>No</p></td></tr><tr><td><p><code>system.instructions</code></p></td><td><p>Overrides the global <code>system.instructions</code> at the file root level for this generator node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>prompt</code></p></td><td><p>Session-specific query or instructions for this particular node, typically containing user provided or user related context.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>outputs</code></p></td><td><p>A schema definition for the agentic output.</p></td><td><p>Object See <a href="#node-outputs">Node Outputs</a></p></td><td><p>No</p></td></tr></tbody></table>

### Executor Node

The executor node executes Agent Script statements deterministically and no LLM is involved. Because
there is no LLM reasoning loop, every action argument must be fully resolved at execution time (you
cannot use slot filling `…​` in an executor). Use this node when you need to call an action with
known arguments, store a computed value in a variable, or chain multiple deterministic steps before
transitioning.

**Example**

```yaml
executor sendHrSlackUpdate:
  do:
    -> run @actions.send_slack_message with text=@generator.generate-hr-slack-update-message.output
    with channel_id="my-onboarding-channel-id"
  on_exit: -> transition to @router.countrySwitch
```

**Example with multiple statements:**

```yaml
executor prepareAndNotify:
  description: "Sets the ticket status variable and sends a Slack notification."
  do:
    -> set @variables.ticketStatus = "resolved" run @actions.send_slack_message with text="Ticket "
    + @generator.classifySeverity.output.ticket_id + " resolved" with
    channel_id=@variables.notificationChannel
  on_exit: -> transition to @echo.finalResponse
```

The executor node has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>on_exit</code></p></td><td><p>A procedure that executes when the node execution finishes. If <code>on_exit</code> is not defined, the graph ends when the executor ends.</p></td><td><p>Procedure, but only <code>transition_to</code> statements are allowed.</p></td><td><p>No</p></td></tr><tr><td><p><code>do</code></p></td><td><p>A procedure containing one or more Agent Script statements to execute deterministically. See <a href="#executor-supported-statements">Supported Statements in <code>do</code></a>.</p></td><td><p>Procedure</p></td><td><p>Yes</p></td></tr></tbody></table>

#### Supported Statements in `do`

The `do` block accepts a procedure (`→`) containing one or more of these statements:

<table><colgroup><col> <col> <col></colgroup><thead><tr><th>Statement</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td><p><code>run @actions.&lt;name&gt;</code></p></td><td><p>Invoke a defined action. Use <code>with</code> to bind arguments from variables, node outputs, or literal values. All arguments must be fully resolved (no slot filling). Multiple <code>with</code> clauses can be chained.</p></td><td><p><code>run @actions.escalate</code> or <code>run @actions.send_slack_message with text=@generator.summary.output with channel_id="my-channel"</code></p></td></tr><tr><td><p><code>set @variables.&lt;name&gt; = &lt;expression&gt;</code></p></td><td><p>Store a value in a workflow variable for use in downstream nodes.</p></td><td><p><code>set @variables.ticketStatus = "escalated"</code></p></td></tr></tbody></table>

### Router Node

The router node performs dynamic transitions based on deterministic conditions. This node doesn’t
support `transition to` in its `on_exit` attribute. Use this node for branching based on structured
output from a previous node.

**Example**

```yaml
router countryRouter:
   routes:
     - target: @orchestrator.argentinaOnboard
       when: @orchestrator.hrSystemOnboard.output.country  == "ARG"
       label: "Argentina"
     - target: @orchestrator.usOnboard
       when: @orchestrator.hrSystemOnboard.output.country  == "USA"
       label: "USA"
   otherwise:
     target: @echo.invalidCountryResponse
```

The router node has these properties.

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>routes</code></p></td><td><p>An array of condition and target pairs, plus an optional label field for UI. Must define at least one route. Each route contains: <code>target</code>, <code>when</code>, and optional <code>label</code>.</p></td><td><p>Array</p></td><td><p>Yes</p></td></tr><tr><td><p><code>otherwise</code></p></td><td><p>Defines a default transition when no route condition matches. Contains: <code>target</code>.</p></td><td><p>Object</p></td><td><p>Yes with <code>routes</code></p></td></tr></tbody></table>

### Echo Node

The echo node sends a response back to the client. The number of responses depends on the trigger
interface and its configuration. Use this node for the end of a workflow, or anytime you want to
emit a response.

**Example**

```yaml
echo addArtifact:
  kind: "a2a:artifact_update_event"
  artifact: a2a.artifact({
    artifactId: uuid(),
    name: "myArtifact",
    description: "this is optional",
    parts: [
      a2a.textPart("You have been onboarded! Your employee ID is " + @orchestrator.hrSystemOnboard.output.employeeId)
    ],
    metadata: {},
  }),
  append: false
  lastChunk: false

echo setStatus:
  kind: "a2a:status_update_event"
  state: "TASK_STATE_COMPLETED",
  message: a2a.message({
    messageId: uuid(),
    parts: [
      a2a.textPart("You have been onboarded! Your employee ID is " + @orchestrator.hrSystemOnboard.output.employeeId)
    ]
  })
```

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Description</th><th>Type</th><th>Required</th></tr></thead><tbody><tr><td><p><code>id</code></p></td><td><p>The node identifier, defined next to the node type.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>label</code></p></td><td><p>An optional short, human-readable display name for the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>description</code></p></td><td><p>A CommonMark string providing a description of the node.</p></td><td><p>String</p></td><td><p>No</p></td></tr><tr><td><p><code>on_exit</code></p></td><td><p>A procedure that executes when the node execution finishes. If <code>on_exit</code> is not defined, the graph ends when the agentic node loop ends.</p></td><td><p>Procedure, but only <code>transition_to</code> statements are allowed.</p></td><td><p>No</p></td></tr><tr><td><p><code>kind</code></p></td><td><p>Discriminator for the event type. Valid values: <code>a2a:status_update_event</code>, <code>a2a:artifact_update_event</code>.</p></td><td><p>String</p></td><td><p>Yes</p></td></tr><tr><td><p><code>state</code></p></td><td><p>The task state. Used with <code>a2a:status_update_event</code> kind.</p></td><td><p>String</p></td><td><p>Yes (for <code>status_update_event</code>)</p></td></tr><tr><td><p><code>message</code></p></td><td><p>A message object created via <code>a2a.message()</code>. Used with <code>a2a:status_update_event</code> kind.</p></td><td><p>Message object</p></td><td><p>Yes (for <code>status_update_event</code>)</p></td></tr><tr><td><p><code>artifact</code></p></td><td><p>An artifact object created via <code>a2a.artifact()</code>. Used with <code>a2a:artifact_update_event</code> kind.</p></td><td><p>Artifact object</p></td><td><p>Yes (for <code>artifact_update_event</code>)</p></td></tr><tr><td><p><code>append</code></p></td><td><p>Whether to append to an existing artifact. Used with <code>a2a:artifact_update_event</code> kind.</p></td><td><p>Boolean</p></td><td><p>No</p></td></tr><tr><td><p><code>lastChunk</code></p></td><td><p>Whether this is the last chunk of the artifact. Used with <code>a2a:artifact_update_event</code> kind.</p></td><td><p>Boolean</p></td><td><p>No</p></td></tr><tr><td><p><code>metadata</code></p></td><td><p>Optional metadata dictionary.</p></td><td><p>dict</p></td><td><p>No</p></td></tr></tbody></table>

The following table summarizes echo node parameters organized by `kind`.

<table><colgroup><col> <col> <col></colgroup><thead><tr><th>Kind</th><th>Required Parameters</th><th>Optional Parameters</th></tr></thead><tbody><tr><td><p><code>a2a:artifact_update_event</code></p></td><td><p><code>artifact</code> (object created via <code>a2a.artifact()</code>)</p></td><td><p><code>append</code> (boolean), <code>lastChunk</code> (boolean)</p></td></tr><tr><td><p><code>a2a:status_update_event</code></p></td><td><p><code>state</code> (string), <code>message</code> (object created via <code>a2a.message()</code>)</p></td><td><p><code>metadata</code> (dict)</p></td></tr></tbody></table>

#### Echo Node Behavior

The following table describes echo node behavior based on the A2A operation used by the client.

<table><colgroup><col> <col></colgroup><thead><tr><th>Operation / Condition</th><th>Echo Behavior</th></tr></thead><tbody><tr><td><p><code>SendMessage</code> with <code>returnImmediately = false</code></p></td><td><p>Each echo invocation updates the stored task. Each echo invocation emits a push notification payload for all created push notifications. A consolidated response is emitted when the graph ends or is suspended.</p></td></tr><tr><td><p><code>SendMessage</code> with <code>returnImmediately = true</code></p></td><td><p>An immediate response is sent before graph execution is triggered. The response includes the task and context ID. A stored task entry with the response already exists before graph execution begins. All echo invocations update the stored task atomically (including consolidated and individual events). Each echo invocation emits a push notification payload for all created push notifications.</p></td></tr><tr><td><p><code>SendStreamingMessage</code></p></td><td><p>All echo invocations update the stored task atomically (including consolidated and individual events). All individual events are sent through the event stream. Each echo invocation emits a push notification payload for all created push notifications.</p></td></tr><tr><td><p><code>SubscribeToTask</code></p></td><td><p>This condition works on top of the scenarios above. Any task in a non-terminal state can be subscribed to. Whenever echo is executed, events are pushed to all subscribed clients.</p></td></tr></tbody></table>

## A2A Namespace Functions

The `a2a` namespace provides a set of functions that support A2A Task object creation. Do not prefix
these functions with `@` as it’s reserved for references such as `@variables`, `@actions`,
`@request`, and `@orchestrator.<nodeId>`.

<table><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th>Function</th><th>Description</th><th>Input Arguments</th><th>Output</th><th>Example</th></tr></thead><tbody><tr><td><p><code>a2a.message</code></p></td><td><p>Builds an A2A Message object</p></td><td><p><code>messageId: str</code> (required) <code>parts: list</code> (required, from <code>a2a.textPart/a2a.dataPart/a2a.filePart</code>) <code>role: str</code> (optional, default: "agent") <code>metadata: dict</code> (optional)</p></td><td><p><code>dict</code> (Message)</p></td><td><p><code>a2a.message({messageId: uuid(), parts: [a2a.textPart("Hello")]})</code></p></td></tr><tr><td><p><code>a2a.textPart</code></p></td><td><p>Builds a TextPart object (kind: "text")</p></td><td><p><code>text: str</code> (required) <code>metadata: dict</code> (optional)</p></td><td><p><code>dict</code> (TextPart)</p></td><td><p><code>a2a.textPart("Employee ID: {!@orchestrator.employee.id}") <code>a2a.textPart("Status: Complete", metadata={priority: "high"})</code></code></p></td></tr><tr><td><p><code>a2a.dataPart</code></p></td><td><p>Builds a DataPart object (kind: "data")</p></td><td><p><code>data: dict</code> (required) <code>metadata: dict</code> (optional)</p></td><td><p><code>dict</code> (DataPart)</p></td><td><p><code>a2a.dataPart({employeeId: "E123", department: "Engineering"}) <code>a2a.dataPart(@orchestrator.result.output)</code></code></p></td></tr><tr><td><p><code>a2a.filePart</code></p></td><td><p>Builds a FilePart object (kind: "file")</p></td><td><p><code>uri: str</code> (optional, required if bytes not provided) <code>bytes: str</code> (optional, base64-encoded) <code>name: str</code> (optional) <code>mime_type: str</code> (optional) <code>metadata: dict</code> (optional)</p></td><td><p><code>dict</code> (FilePart)</p></td><td><p><code>a2a.filePart(uri="https://example.com/report.pdf", name="report.pdf", mime_type="application/pdf") a2a.filePart(bytes="SGVsbG8gV29ybGQ=", name="data.txt")</code></p></td></tr><tr><td><p><code>a2a.artifact</code></p></td><td><p>Builds an A2A Artifact object</p></td><td><p><code>artifactId: str</code> (optional, auto-generated) <code>name: str</code> (optional) <code>description: str</code> (optional) <code>parts: list</code> (required, from <code>a2a.textPart/a2a.dataPart/a2a.filePart</code>) <code>metadata: dict</code> (optional)</p></td><td><p><code>dict</code> (Artifact)</p></td><td><p><code>a2a.artifact({artifactId: uuid(), name: "Results", parts: [a2a.dataPart(…​)]})</code></p></td></tr></tbody></table>

Usage notes:

- Functions are designed to be composed: `a2a.message` and `a2a.artifact` accept `parts` created by
  `a2a.textPart`/`a2a.dataPart`/`a2a.filePart`.

- `a2a.filePart` requires either `uri` OR `bytes` (base64-encoded), but not both.

- `a2a.artifact` auto-generates `artifactId` if it’s not provided.

- All `metadata` parameters are optional and accept arbitrary dictionaries.

- For tasks, it’s not necessary to define the `id`, `contextId` and `history` attributes, those are
  automatically populated by the trigger.

## Built-in Functions

Use these functions in expressions alongside references and interpolations. They include time and ID
helpers (`now`, `uuid`), string utilities (`strip`, `startswith`, and `endswith`), JSON parsing
(`parse_json`), and common numeric helpers (`abs`, `round`, and `sum`) for deterministic math-style
logic without calling external tools.

<table><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th>Function</th><th>Description</th><th>Input arguments</th><th>Output</th><th>Example</th></tr></thead><tbody><tr><td><p><code>now</code></p></td><td><p>Current UTC time in ISO 8601 format</p></td><td><p>None</p></td><td><p>String (ISO 8601)</p></td><td><p><code>now()</code></p></td></tr><tr><td><p><code>uuid</code></p></td><td><p>Random UUID v4</p></td><td><p>None</p></td><td><p>String (UUID)</p></td><td><p><code>uuid()</code></p></td></tr><tr><td><p><code>strip</code></p></td><td><p>Removes leading/trailing characters from a string</p></td><td><p>String, optional chars (default: whitespace)</p></td><td><p>String</p></td><td><p><code>strip(" hello ") → "hello"</code></p></td></tr><tr><td><p><code>startswith</code></p></td><td><p>Whether a string starts with a prefix</p></td><td><p>String, prefix</p></td><td><p>Boolean</p></td><td><p><code>startswith("hello world", "hello")</code></p></td></tr><tr><td><p><code>endswith</code></p></td><td><p>Whether a string ends with a suffix</p></td><td><p>String, suffix</p></td><td><p>Boolean</p></td><td><p><code>endswith("report.pdf", ".pdf")</code></p></td></tr><tr><td><p><code>abs</code></p></td><td><p>Absolute value</p></td><td><p>Number</p></td><td><p>Number</p></td><td><p><code>abs(-42)</code></p></td></tr><tr><td><p><code>round</code></p></td><td><p>Round to optional digit count</p></td><td><p>Number, optional <code>ndigits</code></p></td><td><p>Number</p></td><td><p><code>round(3.14159, 2)</code></p></td></tr><tr><td><p><code>sum</code></p></td><td><p>Sum of a numeric list</p></td><td><p>List</p></td><td><p>Number</p></td><td><p><code>sum([10, 20, 30])</code></p></td></tr><tr><td><p><code>parse_json</code></p></td><td><p>Parse a JSON string</p></td><td><p>String (valid JSON)</p></td><td><p>Object or array</p></td><td><p><code>parse_json('{"key": "value"}')</code></p></td></tr></tbody></table>

## Node Outputs

Use the `outputs` field to define the expected shape of the agent’s response using a schema notation
similar to a JSON schema. When provided, the agent produces output matching the defined structure
for downstream parsing and processing.

Each property maps to a field in the agent’s output. These types are supported.

**Note:** Advanced JSON schema features are not supported, so do not copy patterns from generic JSON
Schema tutorials unless they match what is documented here.

<table><colgroup><col> <col></colgroup><thead><tr><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><p>String</p></td><td><p>Text values with optional constraints like <code>pattern</code> (regex), <code>minLength</code>, <code>maxLength</code>, and <code>enum</code> (allowed values).</p></td></tr><tr><td><p>Number / Integer</p></td><td><p>Numeric values with optional constraints like <code>minimum</code>, <code>maximum</code>, <code>exclusiveMinimum</code>, <code>exclusiveMaximum</code>, and <code>enum</code>.</p></td></tr><tr><td><p>Boolean</p></td><td><p><code>True</code> or <code>False</code> (with optional default).</p></td></tr><tr><td><p>Array</p></td><td><p>Lists of items, where <code>items</code> define the schema for each element (can be any supported type). Supports <code>minItems</code> and <code>maxItems</code>.</p></td></tr><tr><td><p>Object</p></td><td><p>Nested structures with their own <code>properties</code> map. Supports a <code>required</code> array to specify mandatory fields.</p></td></tr></tbody></table>

Each property definition can include:

- `type`: The data type (required).

- `description`: A human-readable explanation of the property’s purpose.

- `default`: A default value if the property is omitted.

The `outputs` definition doesn’t support:

- `additionalProperties` or similar JSON Schema extensibility flags

- Combinators such as `anyOf`, `oneOf`, or `allOf`

- References or shared definitions (`$ref`, `$defs`)

- Composition beyond nested `object` / `array` structures as described above

## Node Expressions and References

Nodes access data from other parts of the workflow using expressions.

These references are used.

<table><colgroup><col> <col> <col></colgroup><thead><tr><th>Prefix</th><th>Reference</th><th>Example</th></tr></thead><tbody><tr><td><p><code>@llm.</code></p></td><td><p>LLM definitions</p></td><td><p><code>@llm.open-api-llm</code></p></td></tr><tr><td><p><code>@actions.</code></p></td><td><p>action definitions</p></td><td><p><code>@actions.hr_agent</code></p></td></tr><tr><td><p><code>@request.</code></p></td><td><p>Trigger request data</p></td><td><p><code>@request.payload</code>, <code>@request.interface</code></p></td></tr><tr><td><p><code>@request.headers</code></p></td><td><p>HTTP headers (case-insensitive)</p></td><td><p><code>@request.headers["Authorization"]</code></p></td></tr><tr><td><p><code>@variables.</code></p></td><td><p>Workflow variables</p></td><td><p><code>@variables.companyId</code></p></td></tr><tr><td><p><code>@&lt;nodeType&gt;.&lt;nodeId&gt;.</code></p></td><td><p>Node references</p></td><td><p><code>@orchestrator.hrOnboard.output</code></p></td></tr></tbody></table>

### Accessing Node Output and Input

Every node has `.output` (the value it produced) and `.input` (the output of whichever node
transitioned into it).

- If a node doesn’t produce a value (for example, a router), its `.output` is `None`.

- If the preceding node is a trigger, `.input` is `None`.

**Example**

@orchestrator.hrSystemOnboard.output.employeeId # returns the \`employeeId\` property of the object
returned by the \`hrSystemOnboard\` node @generator.writeEmailContent.output # returns the string
generated by the \`writeEmailContent\` node

#### When to Use `.output` vs `.input`

Use `.output` when you know exactly which upstream node you need data from. In a straight-line
graph, `.output` is the simplest approach:

process ──► generate\_email ──► send\_email

- `generate_email` reads `@subagent.process.output` as the source content.

- `send_email` reads `@generator.generate_email.output` as its content.

An expression can target any preceding node in the graph, not only the node immediately before the
current node.

To decouple a node from the path that reached it, use `.input`. In this example,
`@generator.generate_email.input` returns the output from whichever of `node_a`, `node_b`, or
`node_c` transitioned into `generate_email`:

node\_a ──┐ node\_b ──┼──► generate\_email ──► send\_email node\_c ──┘

### Accessing Trigger Data

The `@request` namespace provides access to the trigger’s incoming request data. Use `@request`
expressions to read the payload, headers, and other properties of the request that started the
workflow.

- `@request.payload`: Returns the request payload. For the `on_message` handler of the A2A trigger,
  this expression returns a `SendMessageRequest` object.

- `@request.interface`: Returns the name of the interface that produced the message (for example,
  `a2a`).

For A2A triggers, these additional references are also available:

- `@request.headers`: A case-insensitive dictionary of the HTTP request headers. For example,
  `@request.headers["Authorization"]` and `@request.headers["authorization"]` return the same value.

- `@request.taskId`: The current A2A task ID, either provided in the request or automatically
  generated by the trigger.

- `@request.contextId`: The current A2A context ID, either provided in the request or automatically
  generated by the trigger.

**Example**

```yaml
reasoning:
  instructions: -> @request.payload.message.parts[0].text
  actions:
    concur: @actions.concur-agent with http_headers = {"Authorization": @request.headers["Authorization"]}
```

### Setting Action Headers

Any actions that connect to an external system often need to set custom headers. Use cases range
from propagating authorization headers (for example, in OBO authentication) to adding custom
correlation information.

For this, both the MCP and A2A actions automatically get an implicit optional `http_headers`
parameter object type that can be used to set those:

```yaml
actions:
   my_hr_agent: @actions.hr_agent     with http_headers = {"Authorization": @request.headers["Authorization"], "X-CorrelationId": @variables.conversationId}
```

### String Interpolation

Use `{!expression}` to embed values inside strings.

**Example**

```yaml
prompt: "The employee's country is {!@orchestrator.hrOnboard.output.country}"
```

### Slot Filling

Use slot filling (`…​`) to tell an LLM to figure out a value.

**Example**

```yaml
actions:
   send_message: @actions.send_slack_message     with message = ...
    # LLM decides the message content
```

### Tool Binding at the Node Level

When you reference a tool inside a node, you can fix, default, or slot-fill its arguments using
`with`.

**Example**

```yaml
actions:
   # All arguments via slot filling (LLM decides everything)
   sendToDefault: @actions.send_slack
   # Fix the channel, LLM fills the message
   sendToFixed: @actions.send_slack     with channel = "agent-fabric"
   # Fix everything -- fully deterministic
   fullyDeterministic: @actions.send_slack     with message = @variables.calculatedMessage     with channel = @variables.channelId
```
