
Agent Script is a language used to build agents in Agentforce Builder. It uses natural language for conversations and programmatic logic for business rules.
But simple goals often require thoughtful engineering. Let's break down how the agent is structured and why each decision matters.
How to create agentscript
- Click on app launcher and search for Agentforce Studio.
- Now click on New Agent button to create a new agent.
- New page will be open and where you can go with custom agent and ready-made agents. We will go with custom agent.
- Enter the purpose of your agent or what you'd like it to do.
- Now click Send button. to generate the agent.
- It will generate the agent script based on your purpose and here is the final script you can follow:
The system block
The system block gives general instructions to the agent. It also includes message prompts used in different situations. The welcome and error messages are required.
For multiline messages, use the pipe symbol (|). To personalize messages, you can use variables. For example, use {!@variables.userPreferredName} to show the user’s name in the welcome message.
system: instructions: "You are a friendly and empathetic agent that helps customers with their questions." messages: error: "Sorry, something went wrong." welcome: "Hello! How are you feeling today?"
The config block
Every Agentforce agent starts with a config block that establishes identity. This block define metadata about the agent such as its name, agent user, label etc. Here "default_agent_user" is a einstein user that will be used to invoke the agent. Make sure you have created this user in salesforce and have assigned appropriate permissions to it. We can add more property in config block:
| Parameter | Description |
|---|---|
developer_name | The Salesforce API name of the agent (max 80 chars). Must start with a letter, contain only alphanumeric and underscores, and can't end with underscore or have consecutive underscores. Must be unique in your org - you can't have two agents with the same developer_name. |
default_agent_user | API name or ID of the default Salesforce user that is used to run this agent. Required for AgentforceServiceAgent, ignored for AgentforceEmployeeAgent. |
agent_label | Optional. The agent's label, displayed in the UI. Auto-generated from developer_name if not provided. |
description | Description of the agent's goals and purpose. |
company | Optional. Information about your company. |
role | Optional. The agent's role. For example, "Help the customer select the perfect gift." |
agent_version | The agent's version. Set automatically when you create a new version of your agent. |
agent_type | Optional. The type of agent. Currently, allowed values are AgentforceServiceAgent (default) or AgentforceEmployeeAgent. Set automatically when you create an agent from a template. |
enable_enhanced_event_logs | Optional. Indicates whether to enable conversation logging for debugging and monitoring. Allowed values are True or False. Default: False. |
user_locale | Optional. User locale setting. |
config: developer_name: "BookAgent" agent_label: "Book Agent" default_agent_user: "custom_service_agent@00dg5000002y0z71166583081.ext" description: "Show the available books to user"
The variables block
Variables help the agent remember information, track progress, and keep context during a conversation. You define variables in the variables block, and all sub-agents can use them.
There are three types of variables:
- Regular variable: You can give it a default value, and the agent can update it later.
- Linked variable: Its value comes from an output (like an action result). It cannot have a default value.
- System variable: These are already created by the system and ready to use.
Variable naming rules:
- Must start with a letter (not an underscore)
- Can contain letters, numbers, and underscores only
- Cannot end with an underscore
- Cannot have double underscores (__)
- Maximum length is 80 characters
mutable - Optional. Allows the agent to change the variable's value. To ensure a variable's value is never changed, define the variable without mutable.
variables: book_name: mutable string description: "Capture the book name" label: "book name" book_number: mutable string description: "Capture the book number" label: "book number" book_detail: mutable object description: "Store the book detail" label: "book detail" active_flow: mutable string label: "active_flow" description: "Track which workflow is currently in progress. Values: bookDetail or empty string for none."
The agent router
The start agent block (called Agent Router in Canvas view) is a special sub-agent that uses the start_agent prefix. The agent starts from this block every time a user sends a message.
It is used to begin the conversation and decide when to move to other sub-agents. It also handles classification, filtering, and routing of requests.
start_agent agent_router: description: "Welcome the user and determine the appropriate subagent based on user input" reasoning: instructions: -> if @variables.active_flow == "bookInfo": transition to @subagent.book_management | Welcome the guest and analyze their input to determine the most appropriate subagent to handle their request. actions: go_to_book_management: @utils.transition to @subagent.book_management description: "Invoke when user want to request about books"
The pipe character (|) introduces a natural language instruction to the LLM. This is the key design philosophy of Agentforce: declarative conditions check structured state; prose instructions guide the model's language behaviour.
The Topic and Action: connecting AI with Salesforce Data
The Retrieve_Book_Detail action connects the agent to real Salesforce data using an Apex invocable class:
subagent book_management: description: "Show the book detail, summarizes book." reasoning: instructions: -> set @variables.active_flow = "bookInfo" if @variables.book_name is None and @variables.book_name == "" or @variables.book_number is None and @variables.book_number == "": | Ask the customer for book name or book number to get the specific book detail. Invoke {!@actions.set_bookname} to set the book name. Or Invoke {!@actions.set_bookNumber} to set the book number. if @variables.book_name is not None and @variables.book_name != "" or @variables.book_number is not None and @variables.book_number != "": | To find the book detail invoke this action {!@actions.go_to_retrieve_book_detail} set @variables.active_flow = "" actions: set_bookname: @utils.setVariables description: "Set the book name when they provide it." with book_name = ... set_bookNumber: @utils.setVariables description: "Set the book number when they provide it." with book_number = ... go_to_retrieve_book_detail: @actions.Retrieve_Book_Detail with bookName = @variables.book_name with bookNumber = @variables.book_number set @variables.book_detail = @outputs.bookingInformation actions: Retrieve_Book_Detail: label: "Retrieve Book Detail" description: |Display the specific book detail when they provide the book number or book name. target: "apex://BookRetrieveAction" inputs: bookName: string label: "Book Name" description: "Enter the book name" is_required: False complex_data_type_name: "lightning__textType" bookNumber: string label: "Book Number" description: "Enter the book number" is_required: False complex_data_type_name: "lightning__textType" outputs: bookingInformation: object label: "bookingInformation" complex_data_type_name: "@apexClassType/c__BookRetrieveAction$AvailableBookDetail" is_displayable: False filter_from_agent: False
Both inputs are optional — the Apex class handles either a name or a number. The output is a strongly-typed Apex inner class (AvailableBookDetail), ensuring the agent always receives well-structured data it can reason over or display directly to the user.
Putting it all together: a complete Agentforce bot
config: developer_name: "BookAgent" agent_label: "Book Agent" default_agent_user: "custom_service_agent@00dg5000002y0z71166583081.ext" description: "Show the available books to user" system: instructions: "You are a friendly and empathetic agent that helps customers with their questions." messages: error: "Sorry, something went wrong." welcome: "Hello! How are you feeling today? Phenoble is known for its phenomenal work in the field and its relationships with clients are great. Our success stems from our core values, which guide everything we do. We believe in trust, equality, and inclusivity." variables: book_name: mutable string description: "Capture the book name" label: "book name" book_number: mutable string description: "Capture the book number" label: "book number" book_detail: mutable object description: "Store the book detail" label: "book detail" active_flow: mutable string label: "active_flow" description: "Track which workflow is currently in progress. Values: bookDetail or empty string for none." start_agent agent_router: description: "Welcome the user and determine the appropriate subagent based on user input" reasoning: instructions: -> if @variables.active_flow == "bookInfo": transition to @subagent.book_management | Welcome the guest and analyze their input to determine the most appropriate subagent to handle their request. actions: go_to_book_management: @utils.transition to @subagent.book_management description: "Invoke when user want to request about books"