2.1 Deterministic Behavior: Filters, Variables & Template Expressions

Key Takeaways

  • Agentforce variables include context (linked) variables mapped to object fields, custom (mutable) variables, and read-only system variables.
  • Custom variables can store string, number, list, object, or boolean values and are internal by default, but can be made external so the Agent API can set them.
  • Filters, written as available when in Agent Script, make a subagent or action usable only when variable-based conditions are true.
  • Template expressions such as {!@variables.order_id} resolve variable values into prompt text before the prompt reaches the LLM.
  • Context variables such as MessagingSession.ContactId identify a customer but don't control data access; use verification plus filters.
Last updated: September 2026

2.1 Deterministic Behavior: Filters, Variables & Template Expressions

Quick Answer: Use variables to remember facts reliably, filters to control when a subagent or action can be used, and template expressions to put exact values into prompt text. Together with conditional logic, these give you deterministic behavior: the same inputs produce the same path through the agent. Scenario questions often describe an agent that "sometimes" skips a step. The fix is almost always a variable-based filter or logic, not a louder instruction.

Variables

Variables let an agent deterministically remember information across turns, track progress, and share values between subagents and actions. In Agent Script, variables are declared in the variables block and referenced as @variables.name.

Variable typeAlso calledWhere the value comes fromCan it change?
Context variableLinked variableMapped to an object field, such as a Messaging Session field (custom fields supported)Populated from its source
Custom variableMutable variableSet by logic, action outputs, or the LLM through the set-variables utilityYes, during the session
System variablePredefined by Agentforce for the sessionNo (read-only)

Custom variables can store string, number, list, object, or boolean values and hold them only for the conversation session. By default they're internal (set only inside the agent). Marking a variable external lets the Agent API set it.

Examples in Agent Script:

variables:
    RoutableId: linked string
        description: "The messaging session ID"
        source: @MessagingSession.Id
    verified: mutable boolean = False
        description: "Whether the customer passed verification"
    order_summary: mutable string = ""
        description: "Summary of the customer's current order"

System variables are read with @system_variables.name. Two useful ones:

  • @system_variables.user_input – the customer's most recent utterance, not the whole history
  • @system_variables.current_modality"voice" on a telephony connection and "text" on Messaging or Enhanced Chat v2, useful for formatting dates for speech instead of text

Ways to set and use variables

  1. Store an action output: set @variables.order_id = @outputs.order_id
  2. Bind an action input: with order_number = @variables.orderNumber
  3. Let the LLM set it with the @utils.setVariables utility, for example to capture a name the customer typed
  4. Set it directly in logic: set @variables.userName = "New User"
  5. Use it in conditions and filters: if @variables.order_summary == "":

When you run an action inside reasoning instructions, you must set the input and output variables yourself, because the action runs before any reasoning. For actions the LLM chooses during reasoning, variable binding is optional, but it's useful when you need one action's output to feed another.

Filters

A filter ensures an agent can use a subagent or action only when one or more conditions are met. In Canvas view it appears as "Make this action available when:". In Agent Script it's the available when clause on a reasoning action.

start_agent agent_router:
    reasoning:
        actions:
            go_to_identity: @utils.transition to @subagent.Identity_Verification
                description: "Verifies user identity"
                available when @variables.verified == False
            go_to_order: @utils.transition to @subagent.Order_Management
                description: "Handles order lookup, refunds, and order updates"
                available when @variables.verified == True
            go_to_escalation: @utils.transition to @subagent.Escalation
                description: "Transfers to a human representative"
                available when @variables.verified == True and @variables.is_business_hours == True

When a customer isn't verified, the Order Management transition simply isn't offered to the LLM, so it can't route there however the customer phrases the request.

Filters vs. instructions

RequirementWeak approachDeterministic approach
Only verified customers can see orders"Never show orders to unverified users"Filter the subagent or action with @variables.verified == True
Returns allowed only within 60 days"Only offer returns within 60 days"Logic sets return_eligibility from days_since_order, and a filter gates create_return
Escalate only during business hours"Don't transfer after hours"Filter the escalation action on a business-hours variable

In the legacy builder, filters are created on the Filters tab of the Context panel from context, conversation, and custom variables, then applied to topics or actions. The concept is the same.

Template Expressions

A template expression uses {! } to resolve a value into prompt text at runtime:

| Refer to the customer as {!@variables.member_name}.
| Their current order status is {!@variables.order_status}.

If member_name is "Priya" and order_status is "shipped," the LLM receives "Refer to the customer as Priya. Their current order status is shipped." The model sees concrete values instead of being asked to look them up or remember them. Template expressions can also contain expressions built with supported operators.

ConstructPurposeExample
@variables.x in logicRead a variable in conditions, with, or setif @variables.count > 0:
{!@variables.x} in prompt textInsert the value into what the LLM reads| Your order {!@variables.order_id} ...
... in action inputsAsk the LLM to slot-fill from the conversationwith order_id = ...

A common mistake is using ... as a variable's default value. The slot-fill token belongs only in action inputs.

Security Pattern: Identify vs. Authorize

Context variables such as MessagingSession.ContactId tell the agent who the user is but don't control data access. For Service agents running as the agent user, Salesforce recommends this pattern:

  1. Verify the customer, for example with the standard Customer Verification subagent or a custom verification action.
  2. Store the verified ID in the VerifiedCustomerId variable.
  3. Add filters such as VerifiedCustomerId is not None to subagents and actions that expose private data.
  4. Build the same check into the flows and Apex behind those actions, for example WHERE ContactId = VerifiedCustomerId.

Filters stop the agent from offering a sensitive action. Logic inside the action enforces the data scope.

Follow-Up Actions and Deterministic Chaining

In actions available for reasoning, a follow-up action ("After this action is run:") defines what always happens after the LLM chooses and runs an action. It can save outputs to variables, transition to another subagent, or run another action. For example, after validate_user_ready runs, the agent always transitions to the analyze_issue subagent.

Exam Traps

  • Stronger wording isn't a filter. "ALWAYS" and "NEVER" still leave the decision to the LLM.
  • A context variable doesn't enforce security. Knowing a Contact ID doesn't restrict what the agent user can query.
  • Run-in-instructions requires explicit bindings. Without with and set, the action has no inputs and its outputs aren't stored.
  • System variables are read-only. Store derived values in a custom variable.
Test Your Knowledge

A Service agent should offer the Order Management subagent only after the customer passes identity verification. Which configuration enforces this deterministically?

A
B
C
D
Test Your Knowledge

What does the template expression {!@variables.order_status} do inside prompt text?

A
B
C
D
Test Your Knowledge

A developer needs an external web app using the Agent API to pass a customer's loyalty tier into an agent session. How should the custom variable be configured?

A
B
C
D
Test Your Knowledge

A Service agent reads MessagingSession.ContactId into a context variable. Which statement about that variable is accurate?

A
B
C
D