Agent Script is indentation-sensitive. Nesting is determined by indentation level — a child block or field must be indented further than its parent. Spaces are the standard indentation character. Tabs are not recommended and their behavior is implementation-defined. The indentation unit is flexible — any increase in depth relative to the parent is valid; there is no required minimum (e.g. multiples of 2 or 4).
block_a:
child_one: "value"
child_two:
grandchild: "value"
Here child_one and child_two are children of block_a. grandchild is a child of child_two.
Comments begin with # and extend to the end of the line. There is no multi-line comment syntax.
# top-level comment
block_a:
field: "value" # inline comment
Comments may appear at the top level, inline with a field, or between blocks. Note: within a multiline template string (introduced by |), the # character is treated as a comment only if it appears at or shallower than the template's base indentation level. At deeper indentation, # is treated as literal template content. See Section 6: Templating Syntax.
A block is the fundamental structural unit of Agent Script. A block is a key followed by :, optionally followed by a value. Blocks may be nested arbitrarily.
block_a:
field_one: "value"
field_two: 42
Named blocks
Some block types defined by the schema accept an instance name — a second label following the block type, separated by a space:
subagent order_handler:
description: "Handles order inquiries"
Here subagent is the block type and order_handler is the instance name. Whether a block type accepts an instance name is determined by the schema; not all block types support it.
Value types
A block's value may be one of the following forms:
-
Scalar — a string, number, or boolean on the same line as the key (see Section 2: Type System):
label: "My Agent" count: 42 enabled: True -
Sub-block — a nested block, introduced by indentation on the following line:
block_a: field: "value" -
Sequence — a YAML-style list of scalar values or list-maps:
items: - "first" - "second" entries: - key: "name" value: "example" -
Procedure — executable logic, introduced by
->or auto-detected from schema context. See Section 5: Procedure Syntax. -
Template string — a multiline string introduced by
|. See Section 6: Templating Syntax.
Non-primitive values may have indented properties beneath them. These properties are modifiers that annotate or configure the value — they are not nested blocks in the structural sense, but metadata attached to the declaration.
This pattern appears in variable declarations:
status: mutable string = "pending"
description: "The current status of the request"
tags: mutable list[string] = None
description: "List of tags associated with the request"
And in action references within procedures:
reasoning:
actions:
lookup_order: @actions.LookupOrder
description: "Look up order details by order ID"
with order_id=@variables.order_id
The indented properties are defined by the schema for the parent value type. Which properties are valid, required, or optional depends on the schema context.
Agent Script has four scalar types:
| Type | Description | Example |
|---|---|---|
string |
Quoted string value | "hello" |
number |
Integer or floating-point | 42, 3.14 |
boolean |
Boolean value (True or False) |
True |
object |
Untyped structured value | None (default) |
Boolean literals are capitalized: True and False.
Lists are parameterized with an element type using bracket notation:
list[string]
list[number]
list[boolean]
list[object]
object is an untyped structured value. It accepts any nested structure and defaults to None when no value is provided.
Variables are typed declarations that appear wherever the schema permits them. They are not required to be grouped inside a variables block — that is a schema-level convention, not a language requirement. Each declaration specifies a modifier, a name, a type, and an optional default value:
item_count: mutable number = 0
description: "Number of items in the order"
session_id: linked string
description: "Session ID provided by the runtime"
Modifiers
-
mutable— the variable can be read and written from within the agent, including viasetstatements. This is the standard modifier for variables the agent manages. -
linked— the variable is bound to an external value provided by the runtime. It is strictly read-only — it cannot be assigned by any mechanism within the agent, includingset,@utils.setVariables, orwithparameters.
status: mutable string = "pending"
user_id: linked string
retry_count: mutable number = 0
locale: linked string
Type annotation
The type follows the variable name and modifier, separated by a space. A default value may be provided with =. If no default is given, the variable defaults to None.
label: mutable string = "default"
tags: mutable list[string] = None
metadata: mutable object = None
Expressions follow Python-like syntax. The following operators are supported, listed by precedence from lowest to highest:
Logical operators
| Operator | Description |
|---|---|
or |
Logical OR |
and |
Logical AND |
not |
Logical NOT (unary) |
Comparison operators
| Operator | Description |
|---|---|
== |
Equality |
!= |
Inequality |
<, <=, >, >= |
Numeric comparison |
is |
Identity / None check |
is not |
Negated identity / None check |
Arithmetic operators
| Operator | Description |
|---|---|
+, - |
Addition, subtraction |
*, / |
Multiplication, division |
+ (unary), - (unary) |
Unary plus/minus |
Other
| Syntax | Description |
|---|---|
(expr) |
Parenthesized expression |
expr.field |
Member access |
expr[index] |
Subscript / index access |
fn(args) |
Function call |
a if condition else b |
Ternary expression (Python-style, lowest precedence) |
Examples:
@variables.score >= 80
@variables.name != "" and @variables.verified == True
@outputs.result is not None
@outputs.items[0].id
@variables.count + 1
"prefix_" + @variables.label
score if score > 0 else 0
Collection literals: List and dictionary literals are supported in expressions:
[] # empty list
[1, 2, 3] # list literal
{} # empty dict / object
These are most commonly used as default values in variable declarations:
tags: mutable list[object] = []
metadata: mutable object = {}
Type coercion: Agent Script uses loose, Python-like type coercion. Values may be implicitly converted for comparison and arithmetic where the types are compatible. Strict type enforcement is not guaranteed.
Null dereference: Accessing a member of a None value (e.g. @variables.foo.bar when @variables.foo is None) produces a runtime error.
The @ symbol denotes a namespace lookup. A reference of the form @namespace.member resolves the namespace to a registered scope and retrieves member from it.
@variables.order_id
@outputs.temperature_celsius
@actions.LookupOrder
@subagent.billing
@utils.transition
Lookup order
Namespaces are resolved in a defined order. When @foo.bar is evaluated, the runtime searches registered scopes in order until it finds a scope named foo that contains bar, or returns nothing if none is found. The lookup order is:
- Local block scope (e.g. named block instance)
- Parent block scopes, walking up the AST
- Global scopes (injected by the dialect)
Global / injected namespaces
Dialects may inject namespaces into the global scope. These are available everywhere in the script without being declared. For example, @utils is a global namespace injected by supported dialects, providing built-in utilities such as @utils.transition.
Namespace overrides
A dialect may override a global namespace by registering a new scope under the same name. Local or parent scopes also shadow global namespaces of the same name. This allows dialects to extend or replace built-in behaviour without changing the syntax.
References to typed blocks
@ references can refer to named block instances by their block type. The block type name serves as the namespace, and the instance name is the member:
@subagent.billing
@subagent.order_handler
Here subagent is the block type and billing / order_handler are instance names declared elsewhere in the script. This allows procedures to reference other agents, topics, or any named block registered in the schema.
Aliases
Namespaces may have aliases — alternative names that resolve to the same scope. In the AgentScript dialect, @start_agent is an alias for @subagent, so @start_agent.foo and @subagent.foo resolve identically. Aliases are registered per-dialect in the schema info.
Every block in Agent Script has a schema. Schemas are defined in TypeScript using factory functions from @agentscript/language. The schema for a block defines what keys are valid, what types their values must be, and whether fields are required or optional.
The core factory functions are:
| Factory | Description |
|---|---|
Block(name, fields) |
A block with a fixed set of typed fields |
TypedMap(name, valueType) |
A variadic map where keys are user-defined and all values share the same type |
NamedBlock(name, fields) |
A block that accepts an instance name (block_type instance_name:) |
CollectionBlock(block) |
A collection of named blocks of a given type |
Fixed-field blocks
A Block has a predefined set of keys. Unknown keys are a schema error. For example, config and system are fixed-field blocks:
// dialect/agentscript/src/schema.ts
export const ConfigBlock = Block('ConfigBlock', {
description: StringValue,
agent_name: StringValue,
...
});In Agent Script source:
config:
agent_name: "My Agent"
description: "An AI assistant for customer support"
Variadic blocks (TypedMap)
A TypedMap accepts any user-defined keys, all of the same value type. For example, variables and inputs/outputs are variadic:
// packages/language/src/blocks.ts
export const VariablesBlock = TypedMap('VariablesBlock', VariablePropertiesBlock);
export const InputsBlock = TypedMap('InputsBlock', InputPropertiesBlock);In Agent Script source — any key name is valid:
variables:
order_id: mutable string = ""
item_count: mutable number = 0
is_ready: mutable boolean = False
Schemas are defined per-dialect. Dialects extend the base schema by registering additional block types or overriding existing ones. See Section 4.2 for how dialects use discriminators to specialize blocks.
A block may declare a kind field whose value identifies a globally-registered schema type. When present, the block inherits the schema associated with that kind — its fields, validation rules, and defaults. This allows a single block type to represent multiple concrete shapes, selected at authoring time by the value of kind.
The specific kinds available and the schemas they map to are dialect-defined. The mechanism is intentionally left open-ended at the base level to allow dialects to extend it freely.
A procedure is a sequence of statements that executes as the value of a field. The procedure's return type is determined by the schema — a field like instructions expects a string return, while before_reasoning expects a sequence of imperative statements.
Procedures may be introduced explicitly with ->:
reasoning:
instructions: ->
| Greet the user and ask for their order ID.
However, -> is optional. The parser auto-detects procedure context from the schema — if the schema expects a procedure at that position, the arrow may be omitted. Ambiguous cases produce undefined behavior.
When a procedure's return type is string (as determined by the schema), the | operator appends to the output string. Each | line contributes to the final string value, in order.
instructions: ->
| Welcome to customer support.
| I'm here to help you with any issues you're experiencing.
| Please provide your email address to get started.
Conditional logic can be used to build strings dynamically:
instructions: ->
| Hello!
if @variables.customer_verified:
| I can see your account details.
| How can I help you today?
See Section 6 for {!...} interpolation within template strings.
set assigns a value to a variable. The @variables namespace prefix is not required — the identifier is resolved against the variable scope automatically.
set @variables.status = "active"
set @variables.count = @variables.count + 1
Attempting to set a linked variable is an error — linked variables are strictly read-only by any mechanism within the agent. Only mutable variables may be assigned.
run invokes a named action. Unlike function calls in expressions, run is a first-class statement — the action is known to the system, traced, auditable, and supports callbacks.
run @actions.LookupOrder
Actions are referenced via the @actions namespace. The action must be declared in the actions block of the current or enclosing scope.
with binds a value to an input parameter of the preceding run statement. Multiple with clauses may follow a single run.
run @actions.LookupOrder
with order_id=@variables.order_id
with include_history=False
with clauses must immediately follow the run (or each other). The parameter name on the left must match a declared input of the action. Multiple parameters may also be specified in a single with clause using comma separation:
run @actions.UpdatePreferences
with temperature_units=..., default_location=..., notification_settings=...
... is used as a with value to indicate that the parameter should be supplied by the LLM at runtime — i.e. the value is not known statically and is left for the model to determine.
run @actions.SearchKnowledge
with query=...
with category=...
available when is a guard clause on a reasoning action binding. It conditionally makes the action available to the LLM based on a boolean expression. When the condition is false, the action is not presented to the LLM during that reasoning turn. available when is only valid within reasoning.actions — it cannot be used in before_reasoning or after_reasoning.
reasoning:
actions:
create_return: @actions.Create_Return
available when @variables.return_eligible == True
with order_id=@variables.order_id
set @variables.rma_number = @outputs.rma_number
go_to_billing: @utils.transition to @subagent.Billing
available when @variables.verified is True
available when appears as an indented property on a reasoning action binding, before any with clauses.
Conditional branching in procedures uses Python-style if/else syntax. The condition is any valid expression. The body is indented one level.
if @variables.verified:
set @variables.status = "active"
An else clause may follow:
if @variables.verified:
transition to @subagent.Verified
else:
transition to @subagent.Identity
if/else may appear in any procedure context: before_reasoning, after_reasoning, reasoning.instructions, and callbacks. In string-return procedures, | lines inside an if/else block append to the output conditionally:
reasoning:
instructions: ->
| Welcome!
if @variables.verified:
| I can see your account details.
else:
| Please verify your identity first.
Note: elif is not supported. Use nested if/else blocks for multiple conditions.
Callback statements are the statements indented beneath a run block, following any with clauses. They execute after the action returns and have access to the action's outputs via @outputs.
@outputs scoping: @outputs is scoped strictly to the callback block of the action that produced it. It is an implied parameter — conceptually (outputs) -> — and is not accessible outside the callback. Once the callback block ends, @outputs is no longer in scope.
run @actions.VerifyCustomer
with email=@variables.customer_email
set @variables.verified = @outputs.customer_found
set @variables.customer_id = @outputs.customer_id
transition to @subagent.verified_flow
Statement ordering: A callback block has two phases, executed in order:
- Input bindings —
withandtoclauses. These bind inputs to the action before it executes. - Callback body —
set,run,transition, andif/else. These are syntactic sugar for an implicitthen: ->block that runs after the action returns.
Valid callback statements (phase 2):
set— assign a variable from@outputsor any expressionrun— invoke another action (one level of nesting only)transition— transition to another subagent
Action failure: If an action fails at runtime, the behavior of @outputs and the callback body is undefined — error handling is left to the runtime.
Callbacks are syntactic sugar for a post-action procedure body. Each nested run introduces its own @outputs scope — the inner action's outputs shadow the outer action's outputs within the inner callback. There is no way to access an outer action's @outputs from within an inner callback:
run @actions.OuterAction
with something=...
set @variables.outer_result = @outputs.OuterActionResult # outer @outputs
run @actions.InnerAction
set @variables.inner_result = @outputs.InnerActionResult # inner @outputs
# @outputs.OuterActionResult is NOT accessible here
Nesting is capped at one level deep. This is an intentional design constraint to avoid complex callback chains that are difficult to reason about.
transition to transfers execution to another subagent or execution block. It is a first-class statement, not a function call.
transition to @subagent.billing
transition to may appear in after_reasoning, before_reasoning, or as a callback after a run. The target must be a reference to a valid execution block as defined by the dialect schema.
transition to <target> is a first-class syntax rule — to is not a with parameter but a dedicated keyword in the transition statement. The @utils.transition utility in supported dialects exposes this as an action reference in reasoning blocks:
reasoning:
actions:
go_to_billing: @utils.transition to @subagent.billing
description: "Transfer to billing subagent"
Any field that accepts a string value may be written as a quoted string or as a multiline template string introduced by |. These are equivalent forms:
label: "Hello, welcome!"
label: |
Hello, welcome!
The | introduces a multiline string. The first non-empty line following | establishes the base indentation level. All subsequent lines must be at that level or further indented — content at that level is included in the string, and the template ends when indentation returns to or below the base level.
instructions: |
You are a helpful support agent.
Always verify the customer before proceeding.
This line is indented further and is included as-is.
Back to base level.
Within a procedure that returns a string (e.g. instructions), | appends to the output string. Each | line contributes to the final string in order, allowing conditional logic to build strings dynamically:
instructions: ->
| Welcome to support.
if @variables.verified:
| I can see your account details.
| How can I help you today?
Each | statement appends its content followed by a newline. The final string is the concatenation of all appended lines.
Template strings support expression interpolation using {! expr }. The expression is evaluated at runtime and its string representation is inserted inline:
instructions: ->
| Hello, {! @variables.customer_name }!
| Your order score is {! @variables.score }/100.
| Next step: {! @variables.next_step }
Expressions inside {!...} follow the same syntax as Section 3 — any valid expression is permitted, including arithmetic and member access:
| Progress: {! @variables.current + 1 } of {! @variables.total }
| Status: {! @variables.verified if @variables.verified else "unverified" }
Dialect restrictions
A dialect may restrict a string field to disallow template syntax, permitting only quoted string literals. This is enforced at analysis time as an error-level diagnostic (template-in-deterministic-procedure). The restriction is declared in the schema using disallowTemplates() on the field definition.
Actions are named blocks that declare an external tool or function the agent can invoke. They are defined in an actions block and referenced in procedures via run or in reasoning via @actions.Name.
actions:
LookupOrder:
description: "Retrieve order details by order number"
inputs:
order_number: string
description: "The order number to look up"
is_required: True
outputs:
status: string
description: "Current order status"
target: "flow://Lookup_Order_By_Number"
The base schema fields for an action are:
| Field | Type | Description |
|---|---|---|
description |
string | What the action does |
label |
string | Display label (optional) |
inputs |
variadic | Input parameter declarations |
outputs |
variadic | Output parameter declarations |
target |
string | URI identifying the external implementation |
source |
string | Global namespace function name or legacy identifier |
Additional fields (e.g. require_user_confirmation, include_in_progress_indicator) are dialect-specific extensions.
Inputs and outputs are variadic blocks — each key is a user-defined parameter name, and its value is a typed declaration with optional properties:
inputs:
order_number: string
description: "The order number to look up"
is_required: True
outputs:
status: string
description: "Current order status"
items: list[object]
description: "Items in the order"
Which properties are valid on inputs and outputs (e.g. is_required, is_user_input, is_displayable) is dialect-defined.
The target field is a URI string that identifies the external implementation of the action. The URI scheme determines how the runtime resolves the action. URI schemes are defined by the base compiler and extended by dialects. Examples from the agentforce dialect:
target: "flow://Flow_API_Name"
target: "apex://Apex_Class_Name"
target: "externalService://endpoint_name"
target: "standardInvocableAction://Action_Name"
The base compiler provides the URI schema — dialects may register additional schemes or constrain which schemes are valid for a given action type.
Action blocks may be extended by dialects to add fields, tighten validation, or override defaults. This is done via ActionBlock.extend(...) in the dialect schema definition. Extended action blocks inherit all base fields and may add or override any of them.
The AgentScript dialect defines the standard block types for authoring agents. It is the base dialect from which others (agentforce, agentfabric) extend.
Schema defined in: dialect/agentscript/src/schema.ts
Note on
topicvssubagent: Some examples and earlier versions of the language usetopicas a block type.topicis agentforce-dialect-specific and is being deprecated in favor ofsubagent, which is the canonical term in the base dialect. All new scripts should usesubagent.
System-level instructions and default messages for the agent. Appears at the top level of the script. Also available as a scoped override inside subagent blocks (where only instructions is permitted).
Type: string / template
Global system instructions inherited by all subagents. Supports {!...} interpolation. Each subagent inherits these instructions unless it provides its own system.instructions override.
system:
instructions: |
You are a helpful support agent.
Always verify the customer before accessing account details.
Type: block — see messages
Pre-defined message templates for standard runtime situations.
system:
messages:
welcome: "Hello! How can I help you today?"
error: "Sorry, something went wrong. Please try again."
High-level agent configuration. The base dialect provides description; dialects may extend this block with additional fields. See the relevant dialect spec for the full list.
A variadic block of typed variable declarations. Top-level only — not scoped to individual subagents. Keys are user-defined names; values are typed declarations with optional modifiers and defaults. See Part I §2.3.
Lifetime and scope: Variables are global across the entire script. Their state persists across turns and across transitions between subagents — a variable set in subagent.A is visible in subagent.B after a transition.
Variables should include a description field. Descriptions are used by the LLM to understand what a variable holds, and are required for slot-filling via @utils.setVariables — the LLM uses the description to determine what value from the conversation to assign.
variables:
order_id: mutable string = ""
description: "The current order ID being discussed"
verified: mutable boolean = False
description: "Whether the customer has been identity-verified"
session_id: linked string
description: "Session ID provided by the runtime"
The entry-point agent block. Exactly one start_agent is required per script — it is the first subagent the runtime activates. Its instance name is used as the agent identifier. Shares all fields with subagent. @start_agent is an alias for @subagent.
start_agent topic_selector:
description: "Welcome user and route to the right subagent"
reasoning:
instructions: ->
| Welcome the user and route their request.
actions:
go_to_orders: @utils.transition to @subagent.Order_Management
description: "Handle order inquiries"
go_to_returns: @utils.transition to @subagent.Return_Management
description: "Handle return requests"
A named agent block defining logic for a specific conversation area. Multiple subagents may be defined. start_agent or other subagents route to them via transition.
Type: string — string literals only, no templates
Display label shown in the UI. Not provided to the LLM.
Type: string — required
Describes this subagent's purpose. Used by the runtime to determine when to transition to this subagent.
Type: block (instructions only)
An optional per-subagent override of the system instructions. Only the instructions field is available here (not messages).
system:
instructions: "Focus on order lookups. Never expose internal record IDs."
Type: collection of named action blocks
Action definitions available within this subagent. See Part I §7.
Type: procedure — templates disallowed
Runs once per turn, before the LLM reasoning loop starts. May contain set, run, transition, and if/else logic. Template strings (|) are not permitted.
before_reasoning:
if @variables.verified is not True:
transition to @subagent.Identity
run @actions.Check_Business_Hours
set @variables.is_open = @outputs.is_business_hours
Type: block — see reasoning
The reasoning loop block containing LLM instructions and action bindings.
Type: procedure — templates disallowed
Runs once per turn, after the LLM reasoning loop completes. Same constraints as before_reasoning.
after_reasoning:
if @variables.escalation_required:
transition to @subagent.Escalation
set @variables.turn_count = @variables.turn_count + 1
Full example:
subagent Order_Management:
description: "Handles order lookups and updates"
system:
instructions: "Focus on helping the user with their order."
before_reasoning:
if @variables.verified is not True:
transition to @subagent.Identity
actions:
Lookup_Order:
description: "Retrieve order details"
inputs:
order_number: string
is_required: True
outputs:
status: string
order_id: string
target: "flow://Lookup_Order"
reasoning:
instructions: ->
| Ask for the order number and call {!@actions.lookup_order}.
| Never show the record ID: {!@variables.order_id}
actions:
lookup_order: @actions.Lookup_Order
with order_number=...
set @variables.status = @outputs.status
set @variables.order_id = @outputs.order_id
go_to_returns: @utils.transition to @subagent.Returns
description: "Route when user wants to return items"
after_reasoning:
set @variables.request_count = @variables.request_count + 1
A procedure block that runs before the reasoning loop on each turn. Valid statements: set, run (with callbacks), transition, if/else. Template strings (|) are not permitted — this block is deterministic and not LLM-driven.
The reasoning loop block. Drives the LLM's behavior for a given turn.
Loop termination: The reasoning loop iterates until the LLM produces a generation (a response to the user) rather than invoking another action. Each iteration the LLM chooses to either call an action or generate a response. When it generates a response, the loop terminates and after_reasoning is called.
Type: procedure with string return
Instructions provided to the LLM. Re-evaluated on every iteration of the reasoning loop, allowing the prompt to reflect the latest variable state. Supports template strings (|), {!...} interpolation, and conditional logic to build context-sensitive prompts.
reasoning:
instructions: ->
| Help the user with their order.
if @variables.verified:
| The customer is verified. Their order ID is {!@variables.order_id}.
| Always be concise and professional.
Type: collection of reasoning action bindings
Action bindings made available to the LLM during reasoning. Each binding references a declared action and optionally provides description, available when, with clauses, and callbacks.
reasoning:
actions:
lookup_order: @actions.Lookup_Order
description: "Look up an order by number"
available when @variables.order_number != ""
with order_number=@variables.order_number
set @variables.status = @outputs.status
go_to_returns: @utils.transition to @subagent.Returns
description: "Route to returns when user wants to return items"
available when @variables.verified is True
capture_info: @utils.setVariables
description: "Capture order number from conversation"
with order_number=...
escalate: @utils.escalate
description: "Hand off to a human agent"
A procedure block that runs after the reasoning loop on each turn. Same constraints as before_reasoning — deterministic, no template strings.
A named collection of action definitions. Each action is a NamedBlock with a user-defined key. See Part I §7 for full action definition syntax.
A reference to an externally-deployed agent identified by URI. The URI follows the same scheme pattern as action targets — the scheme is a runtime plugin. See Part I §7.3.
Type: string — required, string literals only
URI identifying the connected agent. The scheme determines how the runtime resolves and invokes it (e.g. "agentforce://Billing_Agent").
Type: string
Human-readable label for the connected agent.
Type: string
Description of the connected agent's capabilities.
connected_subagent External_Billing:
target: "agentforce://Billing_Agent"
description: "Handles complex billing disputes requiring specialist review"
Built-in utility actions injected as a global namespace by the AgentScript dialect. Available as action bindings in reasoning.actions or as statements in before_reasoning/after_reasoning.
Transitions execution to another subagent. Used with the to keyword to specify the target. See Part I §5.10.
go_to_billing: @utils.transition to @subagent.Billing
description: "Route to billing subagent"
available when @variables.verified is True
Sets one or more agent variables from the current conversation context. The LLM determines the values based on the conversation and the description of each variable. Inputs use ... to indicate LLM-filled values.
capture_info: @utils.setVariables
description: "Capture customer name and email from the conversation"
with customer_name=...
with customer_email=...
The descriptions on the target variables (declared in variables:) are used by the LLM to understand what to extract from the conversation.
Hands off the conversation to a human agent. Takes no inputs.
escalate: @utils.escalate
description: "Hand off to a live agent when the user requests it"
Runtime-provided read-only variables injected as a global namespace. Available via @system_variables.member.
The raw text input from the user for the current turn.
if @system_variables.user_input is not None:
run @actions.Log_Input
with text=@system_variables.user_input