sf-ai-agentscript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSF-AI-AgentScript Skill
SF-AI-AgentScript 技能
"Prompt engineering is like writing laws in poetry - beautiful, but not enforceable."
Agent Script transforms agent development from prompt-based suggestions to code-enforced guarantees. This skill guides you through writing, debugging, testing, and deploying Agentforce agents using the Agent Script DSL.
"提示工程就像用诗歌写法律——优美,但不具备强制执行力。"
Agent Script将智能体开发从基于提示的建议转变为代码强制执行的保障。本技能将指导你使用Agent Script DSL编写、调试、测试和部署Agentforce智能体。
⚠️ CRITICAL WARNINGS
⚠️ 关键警告
API & Version Requirements
API与版本要求
| Requirement | Value | Notes |
|---|---|---|
| API Version | 65.0+ | Required for Agent Script support |
| License | Agentforce | Required for agent authoring |
| Einstein Agent User | Required | Must exist in org for |
| File Extension | | Single file contains entire agent definition |
| 要求 | 取值 | 说明 |
|---|---|---|
| API版本 | 65.0+ | 支持Agent Script的最低版本 |
| 许可证 | Agentforce | 智能体创作所需 |
| Einstein Agent用户 | 必填 | 组织中必须存在该用户以配置 |
| 文件扩展名 | | 单个文件包含完整的智能体定义 |
MANDATORY Pre-Deployment Checks
部署前必须检查项
- MUST be valid - Query:
default_agent_userSELECT Username FROM User WHERE Profile.Name = 'Einstein Agent User' AND IsActive = true - No mixed tabs/spaces - Use consistent indentation (2-space, 3-space, or tabs - never mix)
- Booleans are capitalized - Use /
True, notFalse/truefalse - Exactly one block - Multiple entry points cause compilation failure
start_agent
- 必须有效 - 查询语句:
default_agent_userSELECT Username FROM User WHERE Profile.Name = 'Einstein Agent User' AND IsActive = true - 禁止混合使用制表符和空格 - 使用一致的缩进方式(2空格、3空格或制表符,切勿混合)
- 布尔值首字母大写 - 使用/
True,而非False/truefalse - 仅存在一个块 - 多个入口点会导致编译失败
start_agent
⛔ SYNTAX CONSTRAINTS (Validated via Testing + Official Spec)
⛔ 语法约束(经测试+官方规范验证)
| Constraint | ❌ WRONG | ✅ CORRECT |
|---|---|---|
| No nested if statements | | |
No top-level | | Actions only inside |
No | | Use |
One | Two | |
| Avoid reserved action names | | |
| | |
| No defaults on linked vars | | |
| Linked vars: no object/list | | Use |
| Post-action only on @actions | | Only |
| agent_name must match folder | Folder: | Both must be identical (case-sensitive) |
| Reserved field names | | Use |
| 约束 | ❌ 错误示例 | ✅ 正确示例 |
|---|---|---|
| 禁止嵌套if语句 | | 使用 |
禁止顶层 | 在根层级定义 | 仅在 |
动作内禁止 | 在动作中定义 | 使用 |
每个动作仅允许一个 | 同一动作包含两个 | 合并为 |
| 避免使用保留动作名称 | | 重命名为 |
| | 使用 |
| 关联变量禁止设置默认值 | | 使用 |
| 关联变量不支持对象/列表类型 | | 使用 |
仅 | 对 | 仅 |
| agent_name必须与文件夹名称一致 | 文件夹名: | 两者必须完全相同(区分大小写) |
| 保留字段名称 | | 使用 |
🔴 Reserved Field Names (Breaking in Recent Releases)
🔴 保留字段名称(近期版本会导致报错)
Common field names that cause parse errors:
❌ RESERVED (cannot use as variable/field names):
description, label, is_required, is_displayable, is_used_by_planner
✅ WORKAROUNDS:
description → descriptions, description_text, desc_field
label → label_text, display_label, label_field常见会导致解析错误的字段名:
❌ 保留字段(不能用作变量/字段名):
description, label, is_required, is_displayable, is_used_by_planner
✅ 替代方案:
description → descriptions, description_text, desc_field
label → label_text, display_label, label_field🔴 Features NOT Valid in Current Release (TDD Validated 2026-01-20)
🔴 当前版本不支持的功能(2026-01-20经TDD验证)
These features appear in documentation or recipes but do NOT compile in Winter '26.
| Feature | Where Mentioned | Error | Status |
|---|---|---|---|
| agentforce.guide | | ❌ NOT valid anywhere |
| agentforce.guide | | ❌ NOT valid anywhere |
| Some docs | | ❌ NOT implemented |
| Recipes | | ❌ NOT valid on |
| Recipes | | ❌ NOT valid on |
| Recipes | | ❌ NOT valid on |
| Recipes | | ❌ May only work on |
What DOES work on actions:
@utils.transitionyaml
actions:
go_next: @utils.transition to @topic.next
description: "Navigate to next topic" # ✅ ONLY this worksNote: Some of these may work onaction targets (not validated). Theflow://utility action has limited property support.@utils.transition
这些功能出现在文档或示例中,但在Winter '26版本中无法编译
| 功能 | 提及来源 | 错误信息 | 状态 |
|---|---|---|---|
主题上的 | agentforce.guide | | ❌ 任何场景均不支持 |
动作上的 | agentforce.guide | | ❌ 任何场景均不支持 |
| 部分文档 | | ❌ 未实现 |
转换动作上的 | 示例代码 | | ❌ 不支持 |
转换动作上的 | 示例代码 | | ❌ 不支持 |
转换动作上的 | 示例代码 | | ❌ 不支持 |
转换动作上的 | 示例代码 | | ❌ 仅可能在 |
@utils.transitionyaml
actions:
go_next: @utils.transition to @topic.next
description: "跳转到下一个主题" # ✅ 仅该属性生效注意:部分属性可能在动作目标上生效(未验证)。flow://工具动作仅支持有限的属性。@utils.transition
🔴 complex_data_type_name
Mapping Table (Critical for Actions)
complex_data_type_name🔴 complex_data_type_name
映射表(动作配置关键)
complex_data_type_name"#1 source of compile errors" - Use this table when defining action inputs/outputs in Agentforce Assets.
| Data Type | | Notes |
|---|---|---|
| (none needed) | Primitive type |
| (none needed) | Primitive type |
| (none needed) | Primitive type |
| | Use for Account, Contact, etc. |
| | Collection of text values |
| | Serialized as JSON text |
| Apex Inner Class | | Namespace required |
| Custom LWC Type | | Custom component types |
| Currency field | | For monetary values |
Pro Tip: Don't manually edit - use the UI dropdown in Agentforce Assets > Action Definition, then export/import the action definition.
complex_data_type_name"编译错误的头号来源" - 在Agentforce资产中定义动作输入/输出时使用此表。
| 数据类型 | | 说明 |
|---|---|---|
| (无需设置) | 原始类型 |
| (无需设置) | 原始类型 |
| (无需设置) | 原始类型 |
| | 用于Account、Contact等对象 |
| | 文本值集合 |
| | 序列化为JSON文本 |
| Apex内部类 | | 必须指定命名空间 |
| 自定义LWC类型 | | 自定义组件类型 |
| 货币字段 | | 用于货币值 |
实用技巧:不要手动编辑 - 在Agentforce资产 > 动作定义中使用UI下拉选择,然后导出/导入动作定义。
complex_data_type_name⚠️ Canvas View Corruption Bugs
⚠️ Canvas视图损坏问题
CRITICAL: Canvas view can silently corrupt Agent Script syntax. Make complex edits in Script view.
| Original Syntax | Canvas Corrupts To | Impact |
|---|---|---|
| | Breaks conditionals |
| | Parse error |
| | Invalid syntax |
| 4-space indent | De-indented (breaks nesting) | Structure lost |
| | Changes return behavior |
| | Breaks compound conditions |
Safe Workflow:
- Use Script view for all structural edits (conditionals, actions, transitions)
- Use Canvas only for visual validation and simple text changes
- Always review in Script view after any Canvas edit
关键提示:Canvas视图可能会静默破坏Agent Script语法。复杂编辑请使用脚本视图。
| 原始语法 | Canvas视图损坏后的结果 | 影响 |
|---|---|---|
| | 破坏条件判断 |
| | 解析错误 |
| | 无效语法 |
| 4空格缩进 | 缩进被移除(破坏嵌套结构) | 丢失代码结构 |
| | 改变返回行为 |
| | 破坏复合条件 |
安全工作流:
- 所有结构性编辑(条件判断、动作、转换)使用脚本视图
- 仅使用Canvas视图进行可视化验证和简单文本修改
- 任何Canvas视图编辑后,务必在脚本视图中检查
⚠️ Preview Mode Critical Bugs
⚠️ 预览模式关键问题
CRITICAL REFRESH BUG: Browser refresh required after every Agent Script save before preview works properly.
| Issue | Error Message | Workaround |
|---|---|---|
| Linked vars in context, not state | | Convert to mutable + hardcode for testing |
| Output property access fails | Silent failure, no error | Assign to variable first, then use in conditional |
| Simulate vs Live behavior differs | Works in Simulate, fails in Live | Test in BOTH modes before committing |
Pattern for Testing Linked Variables:
yaml
undefined关键刷新问题:每次保存Agent Script后,必须刷新浏览器才能正常使用预览功能。
| 问题 | 错误信息 | 解决方法 |
|---|---|---|
| 上下文中的关联变量而非状态变量 | | 转换为可变变量并在测试中硬编码值 |
| 输出属性访问失败 | 无提示失败 | 先赋值给变量,再在条件判断中使用 |
| 模拟与线上行为不一致 | 模拟模式正常,线上模式失败 | 部署前在两种模式中均进行测试 |
关联变量测试模式:
yaml
undefined❌ DOESN'T WORK IN PREVIEW (linked var from session):
❌ 预览模式不生效(来自会话的关联变量):
RoutableId: linked string
source: @MessagingSession.Id
RoutableId: linked string
source: @MessagingSession.Id
✅ WORKAROUND FOR TESTING (hardcode value):
✅ 测试用解决方法(硬编码值):
RoutableId: mutable string = "test-session-123"
description: "MessagingSession Id (hardcoded for testing)"
RoutableId: mutable string = "test-session-123"
description: "MessagingSession ID(测试用硬编码值)"
After testing, switch back to linked for production
测试完成后,切换回关联变量用于生产环境
**Output Property Access Pattern:**
```yaml
**输出属性访问模式**:
```yaml❌ DOESN'T WORK IN PREVIEW (direct output access):
❌ 预览模式不生效(直接访问输出):
if @actions.check_status.result == "approved":
| Approved!
if @actions.check_status.result == "approved":
| 已批准!
✅ CORRECT (assign to variable first):
✅ 正确方式(先赋值给变量):
set @variables.status = @outputs.result
if @variables.status == "approved":
| Approved!
undefinedset @variables.status = @outputs.result
if @variables.status == "approved":
| 已批准!
undefinedNo Nested if
- Two Valid Approaches
if禁止嵌套if - 两种有效写法
yaml
undefinedyaml
undefined❌ WRONG - Nested if (causes SyntaxError)
❌ 错误写法 - 嵌套if(导致SyntaxError)
if @variables.software_cost > 0:
if @variables.software_cost <= 500:
| Auto-approve this software request.
if @variables.software_cost > 0:
if @variables.software_cost <= 500:
| 自动批准该软件申请。
✅ CORRECT Approach 1 - Compound condition (when logic allows)
✅ 正确写法1 - 复合条件(逻辑允许时使用)
if @variables.software_cost > 0 and @variables.software_cost <= 500:
| Auto-approve this software request.
if @variables.software_cost > 0 and @variables.software_cost <= 500:
| 自动批准该软件申请。
✅ CORRECT Approach 2 - Flatten to sequential ifs (for separate messages)
✅ 正确写法2 - 拆分为顺序if(需要单独输出消息时使用)
if @variables.order_verified == False or @variables.payment_confirmed == False:
| ❌ PROCESSING BLOCKED
| Missing requirements:
if @variables.order_verified == False:
| - Order verification pending
if @variables.payment_confirmed == False:
| - Payment confirmation pending
> **When to use each**: Use compound conditions when logic permits (single condition block). Use flattening when you need separate conditional outputs that can't be combined.if @variables.order_verified == False or @variables.payment_confirmed == False:
| ❌ 处理被阻止
| 缺少必要条件:
if @variables.order_verified == False:
| - 订单验证待处理
if @variables.payment_confirmed == False:
| - 付款确认待处理
> **适用场景**:逻辑允许时使用复合条件(单个条件块);需要单独输出不同条件结果时使用拆分写法。...
is Slot-Filling Syntax (LLM Extracts from Conversation)
......
是槽位填充语法(LLM从对话中提取信息)
...yaml
undefinedyaml
undefined❌ WRONG - Using ... as default value
❌ 错误用法 - 将...用作默认值
order_id: mutable string = ...
order_id: mutable string = ...
✅ CORRECT - Use ... only in action parameter binding
✅ 正确用法 - 仅在动作参数绑定中使用...
reasoning:
actions:
search: @actions.search_products
with query=... # LLM extracts from user message
with category=... # LLM decides based on context
with limit=10 # Fixed value
undefinedreasoning:
actions:
search: @actions.search_products
with query=... # LLM从用户消息中提取
with category=... # LLM根据上下文判断
with limit=10 # 固定值
undefinedPost-Action Directives: Only on @actions.*
@actions.*动作后指令:仅适用于@actions.*
@actions.*yaml
undefinedyaml
undefined❌ WRONG - @utils does NOT support set/run/if
❌ 错误写法 - @utils不支持set/run/if
go_next: @utils.transition to @topic.main
set @variables.visited = True # ERROR!
go_next: @utils.transition to @topic.main
set @variables.visited = True # 错误!
✅ CORRECT - Only @actions.* supports post-action
✅ 正确写法 - 仅@actions.*支持动作后操作
process: @actions.process_order
with order_id=@variables.order_id
set @variables.status = @outputs.status # ✅ Works
run @actions.send_notification # ✅ Works
if @outputs.needs_review: # ✅ Works
transition to @topic.review
undefinedprocess: @actions.process_order
with order_id=@variables.order_id
set @variables.status = @outputs.status # ✅ 生效
run @actions.send_notification # ✅ 生效
if @outputs.needs_review: # ✅ 生效
transition to @topic.review
undefinedHelper Topic Pattern (For Demo Agents Without Flows/Apex)
辅助主题模式(无Flow/Apex的演示智能体)
When you need to set variables without backend actions, use dedicated "helper topics":
yaml
undefined当你需要在无后端动作的情况下设置变量时,使用专用的“辅助主题”:
yaml
undefinedMain topic offers LLM-selectable action
主主题提供LLM可选动作
topic verify_employee:
reasoning:
actions:
complete_verification: @utils.transition to @topic.verification_success
description: "Mark employee as verified"
available when @variables.employee_verified == False
topic verify_employee:
reasoning:
actions:
complete_verification: @utils.transition to @topic.verification_success
description: "标记员工为已验证"
available when @variables.employee_verified == False
Helper topic sets variables in instructions, then returns
辅助主题在指令中设置变量,然后返回
topic verification_success:
description: "Set verified state and return"
reasoning:
instructions: ->
set @variables.employee_verified = True
set @variables.employee_name = "Demo Employee"
| ✓ Identity verified!
transition to @topic.verify_employee # Return to parent
> **Why this works**: `set` statements ARE valid inside `instructions: ->` blocks. The topic loop pattern lets you change state without Flows/Apex.
---topic verification_success:
description: "设置验证状态并返回"
reasoning:
instructions: ->
set @variables.employee_verified = True
set @variables.employee_name = "演示员工"
| ✓ 身份验证通过!
transition to @topic.verify_employee # 返回父主题
> **原理**:`set`语句在`instructions: ->`块中是有效的。主题循环模式允许你无需Flow/Apex即可更改状态。
---💰 PRODUCTION GOTCHAS: Billing, Determinism & Performance
💰 生产环境注意事项:计费、确定性与性能
Credit Consumption Table
积分消耗表
Key insight: Framework operations are FREE. Only actions that invoke external services consume credits.
| Operation | Credits | Notes |
|---|---|---|
| FREE | Framework navigation |
| FREE | Framework state management |
| FREE | Framework escalation |
| FREE | Deterministic resolution |
| FREE | Deterministic pre-processing (see note below) |
| FREE | Deterministic post-processing (see note below) |
| FREE | LLM reasoning itself is not billed |
| Prompt Templates | 2-16 | Per invocation (varies by complexity) |
| Flow actions | 20 | Per action execution |
| Apex actions | 20 | Per action execution |
| Any other action | 20 | Per action execution |
✅ Lifecycle Hooks Validated (v1.3.0): Theandbefore_reasoning:lifecycle hooks are now TDD-validated. Content goes directly under the block (noafter_reasoning:wrapper). See "Lifecycle Hooks" section below for correct syntax.instructions:
Cost Optimization Pattern: Fetch data once in , cache in variables, reuse across topics.
before_reasoning:核心要点:框架操作免费。仅调用外部服务的动作会消耗积分。
| 操作 | 积分消耗 | 说明 |
|---|---|---|
| 免费 | 框架导航 |
| 免费 | 框架状态管理 |
| 免费 | 框架升级 |
| 免费 | 确定性解析 |
| 免费 | 确定性预处理(见下文说明) |
| 免费 | 确定性后处理(见下文说明) |
| 免费 | LLM推理本身不收费 |
| 提示模板 | 2-16 | 每次调用(根据复杂度变化) |
| Flow动作 | 20 | 每次动作执行 |
| Apex动作 | 20 | 每次动作执行 |
| 其他任何动作 | 20 | 每次动作执行 |
✅ 生命周期钩子已验证(v1.3.0):和before_reasoning:生命周期钩子现已通过TDD验证。内容需直接放置在块下(无需after_reasoning:包装器)。请查看下文“生命周期钩子”部分的正确语法。instructions:
成本优化模式:在中一次性获取数据,缓存到变量中,在多个主题中复用。
before_reasoning:Lifecycle Hooks: before_reasoning:
and after_reasoning:
before_reasoning:after_reasoning:生命周期钩子:before_reasoning:
和after_reasoning:
before_reasoning:after_reasoning:TDD Validated (2026-01-20): These hooks enable deterministic pre/post-processing around LLM reasoning.
yaml
topic main:
description: "Topic with lifecycle hooks"
# BEFORE: Runs deterministically BEFORE LLM sees instructions
before_reasoning:
# Content goes DIRECTLY here (NO instructions: wrapper!)
set @variables.pre_processed = True
set @variables.customer_tier = "gold"
# LLM reasoning phase
reasoning:
instructions: ->
| Customer tier: {!@variables.customer_tier}
| How can I help you today?
# AFTER: Runs deterministically AFTER LLM finishes reasoning
after_reasoning:
# Content goes DIRECTLY here (NO instructions: wrapper!)
set @variables.interaction_logged = True
if @variables.needs_audit == True:
set @variables.audit_flag = TrueKey Points:
- Content goes directly under /
before_reasoning:(NOafter_reasoning:wrapper)instructions: - Supports ,
set,ifstatements (same as proceduralrun)instructions: -> - is FREE (no credit cost) - use for data prep
before_reasoning: - is FREE (no credit cost) - use for logging, cleanup
after_reasoning:
❌ WRONG Syntax (causes compile error):
yaml
before_reasoning:
instructions: -> # ❌ NO! Don't wrap with instructions:
set @variables.x = True✅ CORRECT Syntax:
yaml
before_reasoning:
set @variables.x = True # ✅ Direct content under the block经TDD验证(2026-01-20):这些钩子支持围绕LLM推理的确定性预处理/后处理。
yaml
topic main:
description: "带生命周期钩子的主题"
# BEFORE: 在LLM处理指令前确定性执行
before_reasoning:
# 内容直接放置在此处(无需instructions:包装器!)
set @variables.pre_processed = True
set @variables.customer_tier = "gold"
# LLM推理阶段
reasoning:
instructions: ->
| 客户等级:{!@variables.customer_tier}
| 今天我能为你提供什么帮助?
# AFTER: 在LLM完成推理后确定性执行
after_reasoning:
# 内容直接放置在此处(无需instructions:包装器!)
set @variables.interaction_logged = True
if @variables.needs_audit == True:
set @variables.audit_flag = True核心要点:
- 内容需直接放置在/
before_reasoning:块下(无需after_reasoning:包装器)instructions: - 支持、
set、if语句(与过程式run相同)instructions: -> - 免费(无积分消耗)- 用于数据准备
before_reasoning: - 免费(无积分消耗)- 用于日志记录、清理
after_reasoning:
❌ 错误语法(导致编译错误):
yaml
before_reasoning:
instructions: -> # ❌ 错误!不要用instructions:包装
set @variables.x = True✅ 正确语法:
yaml
before_reasoning:
set @variables.x = True # ✅ 内容直接放置在块下Supervision vs Handoff (Clarified Terminology)
监督模式 vs 移交模式(术语澄清)
| Term | Syntax | Behavior | Use When |
|---|---|---|---|
| Handoff | | Control transfers completely, child generates final response | Checkout, escalation, terminal states |
| Supervision | | Parent orchestrates, child returns, parent synthesizes | Expert consultation, sub-tasks |
yaml
undefined| 术语 | 语法 | 行为 | 适用场景 |
|---|---|---|---|
| 移交模式 | | 控制权完全转移,子主题生成最终响应 | 结账、升级、终端状态 |
| 监督模式 | | 父主题编排,子主题返回结果,父主题合成响应 | 专家咨询、子任务 |
yaml
undefinedHANDOFF - child topic takes over completely:
移交模式 - 子主题完全接管:
checkout: @utils.transition to @topic.order_checkout
description: "Proceed to checkout"
checkout: @utils.transition to @topic.order_checkout
description: "进入结账流程"
→ @topic.order_checkout generates the user-facing response
→ @topic.order_checkout生成面向用户的响应
SUPERVISION - parent remains in control:
监督模式 - 父主题保持控制权:
get_advice: @topic.product_expert
description: "Consult product expert"
get_advice: @topic.product_expert
description: "咨询产品专家"
→ @topic.product_expert returns, parent topic synthesizes final response
→ @topic.product_expert返回结果,父主题合成最终响应
**KNOWN BUG**: Adding ANY new action in Canvas view may inadvertently change Supervision references to Handoff transitions.
**已知问题**:在Canvas视图中添加任何新动作,可能会无意中将监督模式引用改为移交模式转换。Action Output Flags for Zero-Hallucination Routing
零幻觉路由的动作输出标志
Key Pattern for Determinism: Control what the LLM can see and say.
When defining actions in Agentforce Assets, use these output flags:
| Flag | Effect | Use When |
|---|---|---|
| LLM cannot show this value to user | Preventing hallucinated responses |
| LLM can reason about this value | Decision-making, routing |
Zero-Hallucination Intent Classification Pattern:
yaml
undefined确定性核心模式:控制LLM可见和可输出的内容。
在Agentforce资产中定义动作时,使用以下输出标志:
| 标志 | 效果 | 适用场景 |
|---|---|---|
| LLM无法向用户展示此值 | 防止幻觉响应 |
| LLM可以基于此值进行推理 | 决策、路由 |
零幻觉意图分类模式:
yaml
undefinedIn Agentforce Assets - Action Definition outputs:
在Agentforce资产 - 动作定义输出中:
outputs:
intent_classification: string
is_displayable: False # LLM cannot show this to user
is_used_by_planner: True # LLM can use for routing decisions
outputs:
intent_classification: string
is_displayable: False # LLM无法向用户展示
is_used_by_planner: True # LLM可用于路由决策
In Agent Script - LLM routes but cannot hallucinate:
在Agent Script中 - LLM负责路由但无法产生幻觉:
topic intent_router:
reasoning:
instructions: ->
run @actions.classify_intent
set @variables.intent = @outputs.intent_classification
if @variables.intent == "refund":
transition to @topic.refunds
if @variables.intent == "order_status":
transition to @topic.ordersundefinedtopic intent_router:
reasoning:
instructions: ->
run @actions.classify_intent
set @variables.intent = @outputs.intent_classification
if @variables.intent == "refund":
transition to @topic.refunds
if @variables.intent == "order_status":
transition to @topic.ordersundefinedAction Chaining with run
Keyword
run使用run
关键字的动作链
runKnown quirk: Parent action may complain about inputs needed by chained action - this is expected.
yaml
undefined已知特性:父动作可能会抱怨链式动作所需的输入 - 这是预期行为。
yaml
undefinedChained action execution:
链式动作执行:
process_order: @actions.create_order
with customer_id = @variables.customer_id
run @actions.send_confirmation # Chains after create_order completes
set @variables.order_id = @outputs.id
**KNOWN BUG**: Chained actions with Prompt Templates don't properly map inputs using `Input:Query` format:
```yamlprocess_order: @actions.create_order
with customer_id = @variables.customer_id
run @actions.send_confirmation # 在create_order完成后执行
set @variables.order_id = @outputs.id
**已知问题**:带提示模板的链式动作无法正确使用`Input:Query`格式映射输入:
```yaml❌ MAY NOT WORK with Prompt Templates:
❌ 提示模板可能不生效:
run @actions.transform_recommendation
with "Input:Reco_Input" = @variables.ProductReco
run @actions.transform_recommendation
with "Input:Reco_Input" = @variables.ProductReco
⚠️ TRY THIS (may still have issues):
⚠️ 尝试此写法(仍可能存在问题):
run @actions.transform_recommendation
with Reco_Input = @variables.ProductReco
> **📖 For prompt template action definitions, input binding syntax, and grounded data patterns**, see [resources/action-prompt-templates.md](resources/action-prompt-templates.md). For context-aware descriptions, instruction references (`{!@actions.X}`), and advanced binding strategies, see [resources/action-patterns.md](resources/action-patterns.md).run @actions.transform_recommendation
with Reco_Input = @variables.ProductReco
> **📖 关于提示模板动作定义、输入绑定语法和基于事实的数据模式**,请查看[resources/action-prompt-templates.md](resources/action-prompt-templates.md)。关于上下文感知描述、指令引用(`{!@actions.X}`)和高级绑定策略,请查看[resources/action-patterns.md](resources/action-patterns.md)。Latch Variable Pattern for Topic Re-entry
主题重入的锁存变量模式
Problem: Topic selector doesn't properly re-evaluate after user provides missing input.
Solution: Use a "latch" variable to force re-entry:
yaml
variables:
verification_in_progress: mutable boolean = False
start_agent topic_selector:
reasoning:
instructions: ->
# LATCH CHECK - force re-entry if verification was started
if @variables.verification_in_progress == True:
transition to @topic.verification
| How can I help you today?
actions:
start_verify: @topic.verification
description: "Start identity verification"
# Set latch when user chooses this action
set @variables.verification_in_progress = True
topic verification:
reasoning:
instructions: ->
| Please provide your email to verify your identity.
actions:
verify: @actions.verify_identity
with email = ...
set @variables.verified = @outputs.success
# Clear latch when verification completes
set @variables.verification_in_progress = False问题:用户提供缺失输入后,主题选择器无法正确重新评估。
解决方法:使用“锁存”变量强制重入:
yaml
variables:
verification_in_progress: mutable boolean = False
start_agent topic_selector:
reasoning:
instructions: ->
# 锁存检查 - 如果验证已启动则强制重入
if @variables.verification_in_progress == True:
transition to @topic.verification
| 今天我能为你提供什么帮助?
actions:
start_verify: @topic.verification
description: "开始身份验证"
# 用户选择此动作时设置锁存
set @variables.verification_in_progress = True
topic verification:
reasoning:
instructions: ->
| 请提供你的邮箱以验证身份。
actions:
verify: @actions.verify_identity
with email = ...
set @variables.verified = @outputs.success
# 验证完成后清除锁存
set @variables.verification_in_progress = FalseLoop Protection Guardrail
循环保护机制
Agent Scripts have a built-in guardrail that limits iterations to approximately 3-4 loops before breaking out and returning to the Topic Selector.
Best Practice: Map out your execution paths - particularly topic transitions. Ensure testing covers all paths and specifically check for unintended circular references between topics.
Agent Script内置保护机制,将迭代次数限制在约3-4次循环,之后会中断并返回主题选择器。
最佳实践:规划你的执行路径 - 尤其是主题转换。确保测试覆盖所有路径,并专门检查主题之间意外的循环引用。
Token & Size Limits
令牌与大小限制
| Limit Type | Value | Notes |
|---|---|---|
| Max response size | 1,048,576 bytes (1MB) | Per agent response |
| Plan trace limit (Frontend) | 1M characters | For debugging UI |
| Transformed plan trace (Backend) | 32k tokens | Internal processing |
| Active/Committed Agents per org | 100 max | Org limit |
| 限制类型 | 取值 | 说明 |
|---|---|---|
| 最大响应大小 | 1,048,576字节(1MB) | 每个智能体响应 |
| 前端计划跟踪限制 | 100万字符 | 用于调试UI |
| 后端转换后计划跟踪 | 32k令牌 | 内部处理 |
| 组织中激活/提交的智能体数量上限 | 100个 | 组织限制 |
Progress Indicators
进度指示器
Add user feedback during long-running actions:
yaml
actions:
fetch_data: @actions.get_customer_data
description: "Fetch customer information"
include_in_progress_indicator: True
progress_indicator_message: "Fetching your account details..."在长时间运行的动作中添加用户反馈:
yaml
actions:
fetch_data: @actions.get_customer_data
description: "获取客户信息"
include_in_progress_indicator: True
progress_indicator_message: "正在获取你的账户详情..."VS Code Pull/Push NOT Supported
VS Code拉取/推送不支持
bash
undefinedbash
undefined❌ ERROR when using source tracking:
❌ 使用源跟踪时出错:
Failed to retrieve components using source tracking:
[SfError [UnsupportedBundleTypeError]: Unsupported Bundle Type: AiAuthoringBundle
Failed to retrieve components using source tracking:
[SfError [UnsupportedBundleTypeError]: Unsupported Bundle Type: AiAuthoringBundle
✅ WORKAROUND - Use CLI directly:
✅ 解决方法 - 直接使用CLI:
sf project retrieve start -m AiAuthoringBundle:MyAgent
sf agent publish authoring-bundle --api-name MyAgent -o TARGET_ORG
undefinedsf project retrieve start -m AiAuthoringBundle:MyAgent
sf agent publish authoring-bundle --api-name MyAgent -o TARGET_ORG
undefinedLanguage Block Quirks
语言块特性
- Hebrew and Indonesian appear twice in the language dropdown
- Selecting from the second set causes save errors
- Use for automatic language adaptation
adaptive_response_allowed: True
yaml
language:
locale: en_US
adaptive_response_allowed: True # Allow language adaptation- 希伯来语和印度尼西亚语在语言下拉菜单中显示两次
- 选择第二组会导致保存错误
- 使用实现自动语言适配
adaptive_response_allowed: True
yaml
language:
locale: en_US
adaptive_response_allowed: True # 允许语言适配Cross-Skill Orchestration
跨技能编排
| Direction | Pattern | Priority |
|---|---|---|
| Before Agent Script | | ⚠️ REQUIRED |
| After Agent Script | | ✅ RECOMMENDED |
| For Deployment | | ⚠️ REQUIRED |
Tip: Open Agentforce Studio list view with(v2.121.7+). Open a specific agent withsf org open authoring-bundle -o TARGET_ORG.sf org open agent --api-name MyAgent -o TARGET_ORG
| 方向 | 模式 | 优先级 |
|---|---|---|
| Agent Script之前 | | ⚠️ 必填 |
| Agent Script之后 | | ✅ 推荐 |
| 部署时 | | ⚠️ 必填 |
提示:使用打开Agentforce Studio列表视图(v2.121.7+)。使用sf org open authoring-bundle -o TARGET_ORG打开特定智能体。sf org open agent --api-name MyAgent -o TARGET_ORG
📋 QUICK REFERENCE: Agent Script Syntax
📋 快速参考:Agent Script语法
Block Structure (CORRECTED Order per Official Spec)
块结构(经官方规范修正的顺序)
yaml
config: # 1. Required: Agent metadata (developer_name, agent_type, default_agent_user)
variables: # 2. Optional: State management (mutable/linked)
system: # 3. Required: Global messages and instructions
connections: # 4. Optional: Escalation routing (Service Agents ONLY)
knowledge: # 5. Optional: Knowledge base config
language: # 6. Optional: Locale settings
start_agent: # 7. Required: Entry point (exactly one)
topic: # 8. Required: Conversation topics (one or more)yaml
config: # 1. 必填:智能体元数据(developer_name、agent_type、default_agent_user)
variables: # 2. 可选:状态管理(mutable/linked)
system: # 3. 必填:全局消息和指令
connections: # 4. 可选:升级路由(仅适用于服务智能体)
knowledge: # 5. 可选:知识库配置
language: # 6. 可选:区域设置
start_agent: # 7. 必填:入口点(仅一个)
topic: # 8. 必填:对话主题(至少一个)Config Block Field Names (CRITICAL)
Config块字段名称(关键)
⚠️ Common Error: Using incorrect field names from outdated documentation.
| Documented Field (Wrong) | Actual Field (Correct) | Notes |
|---|---|---|
| | Must match folder name (case-sensitive) |
| | Agent's purpose description |
| (not used) | Remove from examples |
| | ✓ Correct |
| (missing) | | Required: |
yaml
undefined⚠️ 常见错误:使用过时文档中的错误字段名。
| 文档中错误字段 | 实际正确字段 | 说明 |
|---|---|---|
| | 必须与文件夹名称一致(区分大小写) |
| | 智能体用途描述 |
| (未使用) | 从示例中移除 |
| | ✓ 正确 |
| (缺失) | | 必填: |
yaml
undefined✅ CORRECT config block:
✅ 正确的config块:
config:
developer_name: "my_agent"
agent_description: "Handles customer support inquiries"
agent_type: "AgentforceServiceAgent"
default_agent_user: "agent_user@00dxx000001234.ext"
undefinedconfig:
developer_name: "my_agent"
agent_description: "处理客户支持咨询"
agent_type: "AgentforceServiceAgent"
default_agent_user: "agent_user@00dxx000001234.ext"
undefinedNaming Rules (All Identifiers)
命名规则(所有标识符)
- Only letters, numbers, underscores
- Must begin with a letter
- No spaces, no consecutive underscores, cannot end with underscore
- Maximum 80 characters
- 仅允许字母、数字、下划线
- 必须以字母开头
- 无空格、无连续下划线、不能以下划线结尾
- 最大80个字符
Instruction Syntax Patterns
语法模式示例
| Pattern | Purpose | Example |
|---|---|---|
| Literal multi-line (no expressions) | |
| Procedural (enables expressions) | |
| Literal text for LLM prompt | |
| Conditional (resolves before LLM) | |
| Execute action during resolution | |
| Capture action output | |
| Set variable in instructions | |
| Variable injection in text | |
| Conditional interpolation | |
| Control action visibility to LLM | |
| LLM slot-filling (extracts from conversation) | |
| Fixed parameter value | |
| 模式 | 用途 | 示例 |
|---|---|---|
| `instructions: \ | ` | 多行文本(无表达式) |
| 过程式(支持表达式) | |
| `\ | text` | LLM提示文本 |
| 条件判断(LLM处理前解析) | |
| 解析时执行动作 | |
| 捕获动作输出 | |
| 在指令中设置变量 | |
| 文本中的变量注入 | |
| 条件插值 | |
| 控制动作对LLM的可见性 | |
| LLM槽位填充(从对话中提取) | |
| 固定参数值 | |
Transition vs Delegation (CRITICAL DISTINCTION)
转换 vs 委托(关键区别)
| Syntax | Behavior | Returns? | Use When |
|---|---|---|---|
| Permanent handoff | ❌ No | Checkout, escalation, final states |
| Delegation | ✅ Yes | Get expert advice, sub-tasks |
| Deterministic jump | ❌ No | Post-action routing, gates |
yaml
undefined| 语法 | 行为 | 是否返回结果 | 适用场景 |
|---|---|---|---|
| 永久移交 | ❌ 否 | 结账、升级、最终状态 |
| 委托 | ✅ 是 | 获取专家建议、子任务 |
| 确定性跳转 | ❌ 否 | 动作后路由、网关 |
yaml
undefinedDelegation - returns to current topic after specialist finishes
委托 - 专家完成后返回当前主题
consulting: @topic.expert_topic
description: "Get expert advice"
consulting: @topic.expert_topic
description: "获取专家建议"
Transition - permanent handoff, no return
转换 - 永久移交,不返回
checkout: @utils.transition to @topic.checkout
description: "Proceed to purchase"
undefinedcheckout: @utils.transition to @topic.checkout
description: "进入购买流程"
undefinedExpression Operators (Safe Subset)
表达式运算符(安全子集)
| Category | Operators | NOT Supported |
|---|---|---|
| Comparison | | |
| Logical | | |
| Arithmetic | | ❌ |
| Access | | |
| Conditional | |
| 类别 | 支持运算符 | 不支持 |
|---|---|---|
| 比较 | | |
| 逻辑 | | |
| 算术 | | ❌ |
| 访问 | | |
| 条件 | |
Variable Types
变量类型
| Modifier | Behavior | Supported Types | Default Required? |
|---|---|---|---|
| Read/write state | | ✅ Yes |
| Read-only from source | | ❌ No (has |
⚠️ Linked variables CANNOT useorobjecttypeslist
| 修饰符 | 行为 | 支持类型 | 是否需要默认值 |
|---|---|---|---|
| 可读写状态 | | ✅ 是 |
| 从源只读 | | ❌ 否(需 |
⚠️ 关联变量不支持或object类型list
Linked Variable Sources by Agent Type
按智能体类型划分的关联变量源
⚠️ CRITICAL: Not all source bindings work for all agent types.
| Source Pattern | Service Agent | Employee Agent |
|---|---|---|
| ✅ Works | ❌ Not available |
| ✅ Works | ❌ Not available |
| ❓ Untested | ❌ Does not work |
| ❓ Untested | ❌ Does not work |
Workaround for Employee Agents:
Employee Agents in the Copilot panel don't automatically receive record context. Use a mutable variable and have the Flow action look up the current record.
yaml
undefined⚠️ 关键提示:并非所有源绑定对所有智能体类型都生效。
| 源模式 | 服务智能体 | 员工智能体 |
|---|---|---|
| ✅ 生效 | ❌ 不可用 |
| ✅ 生效 | ❌ 不可用 |
| ❓ 未测试 | ❌ 不生效 |
| ❓ 未测试 | ❌ 不生效 |
员工智能体解决方法:
Copilot面板中的员工智能体不会自动接收记录上下文。使用可变变量,让Flow动作查找当前记录。
yaml
undefined❌ DOESN'T WORK for Employee Agents:
❌ 员工智能体不生效:
case_id: linked string
source: @Record.Id
case_id: linked string
source: @Record.Id
✅ WORKAROUND - use mutable variable:
✅ 解决方法 - 使用可变变量:
case_id: mutable string = ""
description: "Case ID - enter or will be looked up by Flow"
undefinedcase_id: mutable string = ""
description: "案例ID - 手动输入或由Flow查找"
undefinedVariable vs Action I/O Type Matrix
变量与动作I/O类型矩阵
Critical distinction: Some types are valid ONLY for action inputs/outputs, NOT for Agent Script variables.
| Type | Variables | Action I/O | Notes |
|---|---|---|---|
| ✅ | ✅ | Universal |
| ✅ | ✅ | Universal |
| ✅ | ✅ | Universal |
| ✅ | ✅ | Universal |
| ✅ | ✅ | Universal |
| ✅ | ✅ | Salesforce IDs |
| ✅ (mutable only) | ✅ | Collections |
| ✅ (mutable only) | ✅ | ⚠️ Not for linked vars |
| ❌ | ✅ | Actions only |
| ❌ | ✅ | Actions only |
| ❌ | ✅ | Actions only |
| ❌ | ✅ | Actions only |
Source: AGENT_SCRIPT.md rules document from trailheadapps/agent-script-recipes
关键区别:部分类型仅对动作输入/输出有效,对Agent Script变量无效。
| 类型 | 变量 | 动作I/O | 说明 |
|---|---|---|---|
| ✅ | ✅ | 通用类型 |
| ✅ | ✅ | 通用类型 |
| ✅ | ✅ | 通用类型 |
| ✅ | ✅ | 通用类型 |
| ✅ | ✅ | 通用类型 |
| ✅ | ✅ | Salesforce ID |
| ✅(仅mutable) | ✅ | 集合 |
| ✅(仅mutable) | ✅ | ⚠️ 不支持关联变量 |
| ❌ | ✅ | 仅动作支持 |
| ❌ | ✅ | 仅动作支持 |
| ❌ | ✅ | 仅动作支持 |
| ❌ | ✅ | 仅动作支持 |
来源:trailheadapps/agent-script-recipes中的AGENT_SCRIPT.md规则文档
Action Target Protocols
动作目标协议
| Short | Long Form | Use When | Validated? |
|---|---|---|---|
| | Data operations, business logic | ✅ TDD |
| | Custom calculations, validation | ✅ TDD |
| | Grounded LLM responses | ✅ TDD |
| | REST API calls | ✅ TDD |
| | RAG knowledge search | ✅ TDD |
| | Third-party APIs via Named Credentials | ✅ TDD |
| | Built-in SF actions (email, tasks) | ✅ TDD |
| | Data Cloud graph queries | 📋 Spec |
| | Data Cloud segment operations | 📋 Spec |
| | Knowledge article triggers | 📋 Spec |
| | Context grounding for LLM | 📋 Spec |
| | Einstein prediction models | 📋 Spec |
| | Execute sub-actions | 📋 Spec |
| | External service calls | 📋 Spec |
| | Salesforce Copilot actions | 📋 Spec |
| (inline) | Topic delegation (returns to parent) | ✅ TDD |
Legend: ✅ TDD = Validated via deployment testing | 📋 Spec = Documented in AGENT_SCRIPT.md spec (requires specific org setup to test)
| 简写 | 完整格式 | 适用场景 | 是否已验证 |
|---|---|---|---|
| | 数据操作、业务逻辑 | ✅ TDD |
| | 自定义计算、验证 | ✅ TDD |
| | 基于事实的LLM响应 | ✅ TDD |
| | REST API调用 | ✅ TDD |
| | RAG知识库搜索 | ✅ TDD |
| | 通过命名凭证调用第三方API | ✅ TDD |
| | 内置SF动作(邮件、任务) | ✅ TDD |
| | 数据云图查询 | 📋 规范 |
| | 数据云分段操作 | 📋 规范 |
| | 知识库文章触发 | 📋 规范 |
| | LLM上下文关联 | 📋 规范 |
| | Einstein预测模型 | 📋 规范 |
| | 执行子动作 | 📋 规范 |
| | 外部服务调用 | 📋 规范 |
| | Salesforce Copilot动作 | 📋 规范 |
| (内联) | 主题委托(返回父主题) | ✅ TDD |
图例:✅ TDD = 经部署测试验证 | 📋 规范 = 记录在AGENT_SCRIPT.md规范中(需要特定组织设置才能测试)
Using Flow and Apex Actions in Agent Script
在Agent Script中使用Flow和Apex动作
For AiAuthoringBundle (Agent Script):andflow://targets work directly — no GenAiFunction registration needed. The target just needs to exist in the org (active Flow or deployed Apex class withapex://).@InvocableMethod
Two-Level Action System (CRITICAL to understand):
Level 1: ACTION DEFINITION (in topic's `actions:` block)
→ Has `target:`, `inputs:`, `outputs:`, `description:`
→ Specifies WHAT to call (e.g., "apex://OrderService")
Level 2: ACTION INVOCATION (in `reasoning.actions:` block)
→ References Level 1 via `@actions.name`
→ Specifies HOW to call it (with/set clauses)Complete Example:
yaml
topic order_status:
description: "Look up order details"
# Level 1: DEFINE the action with a target
actions:
get_case_details:
description: "Fetch case information by ID"
inputs:
case_id: string
description: "The Case record ID"
outputs:
subject: string
description: "Case subject line"
target: "flow://Get_Case_Details" # Flow must exist and be active
reasoning:
instructions: |
Help the customer check their case status.
# Level 2: INVOKE the action defined above
actions:
lookup_case: @actions.get_case_details
with case_id = @variables.case_id
set @variables.case_subject = @outputs.subject⚠️ Common Error:— This means either:ValidationError: Tool target 'X' is not an action definition
- The action is referenced in
viareasoning.actions:but@actions.Xis not defined in the topic'sXblock, ORactions:- The
value points to a Flow/Apex class that doesn't exist in the orgtarget:Fix: Ensure you have BOTH levels: action definition (with) AND action invocation (withtarget:).@actions.name
Agent Builder UI Path (GenAiPlannerBundle — different workflow):
If building agents through the Agent Builder UI (not Agent Script), you DO need GenAiFunction metadata. See for details.
resources/actions-reference.md对于AiAuthoringBundle(Agent Script):和flow://目标直接生效 — 无需注册GenAiFunction。目标只需在组织中存在(激活的Flow或部署的带apex://的Apex类)。@InvocableMethod
两级动作系统(关键理解):
第一级:动作定义(在主题的`actions:`块中)
→ 包含`target:`、`inputs:`、`outputs:`、`description:`
→ 指定要调用的目标(例如"apex://OrderService")
第二级:动作调用(在`reasoning.actions:`块中)
→ 通过`@actions.name`引用第一级定义
→ 指定调用方式(with/set子句)完整示例:
yaml
topic order_status:
description: "查询订单详情"
# 第一级:定义带目标的动作
actions:
get_case_details:
description: "通过ID查询案例信息"
inputs:
case_id: string
description: "案例记录ID"
outputs:
subject: string
description: "案例主题"
target: "flow://Get_Case_Details" # Flow必须存在且已激活
reasoning:
instructions: |
帮助客户查询案例状态。
# 第二级:调用上述定义的动作
actions:
lookup_case: @actions.get_case_details
with case_id = @variables.case_id
set @variables.case_subject = @outputs.subject⚠️ 常见错误:— 这意味着:ValidationError: Tool target 'X' is not an action definition
- 在
中通过reasoning.actions:引用了动作,但@actions.X未在主题的X块中定义,或者actions: 值指向的Flow/Apex类在组织中不存在target:修复方法:确保同时存在两级定义:动作定义(带)和动作调用(带target:)。@actions.name
Agent Builder UI路径(GenAiPlannerBundle — 不同工作流):
如果通过Agent Builder UI(而非Agent Script)构建智能体,需要GenAiFunction元数据。详情请查看。
resources/actions-reference.mdConnection Block (Full Escalation Pattern)
连接块(完整升级模式)
⚠️ Service Agents Only: Theblock is only valid forconnections:. Employee Agents will fail withagent_type: "AgentforceServiceAgent"error. Employee Agents do not support channel-based escalation routing.Unexpected 'connections' block
yaml
connections:
# Messaging channel escalation
connection messaging:
escalation_message: "One moment, I'm transferring our conversation to get you more help."
outbound_route_type: "OmniChannelFlow"
outbound_route_name: "<flow://Escalate_Messaging_To_Live_Agent>"
adaptive_response_allowed: False
# Voice channel escalation
connection voice:
escalation_message: "Please hold while I transfer you to a specialist."
outbound_route_type: "Queue"
outbound_route_name: "Support_Queue"
adaptive_response_allowed: True
# Web chat escalation
connection web:
escalation_message: "Connecting you with a live agent now."
outbound_route_type: "OmniChannelFlow"
outbound_route_name: "<flow://Web_Chat_Escalation>"Key Properties:
| Property | Required | Description |
|---|---|---|
| ✅ | Message shown to user during handoff |
| ✅ | |
| ✅ | Flow API name or Queue name |
| ❌ | Allow LLM to adapt escalation message |
⚠️ 仅服务智能体支持:块仅对connections:有效。员工智能体使用会出现agent_type: "AgentforceServiceAgent"错误。员工智能体不支持基于渠道的升级路由。Unexpected 'connections' block
yaml
connections:
# 消息渠道升级
connection messaging:
escalation_message: "请稍候,我将为你转接人工客服以获得更多帮助。"
outbound_route_type: "OmniChannelFlow"
outbound_route_name: "<flow://Escalate_Messaging_To_Live_Agent>"
adaptive_response_allowed: False
# 语音渠道升级
connection voice:
escalation_message: "请稍等,我将为你转接专家。"
outbound_route_type: "Queue"
outbound_route_name: "Support_Queue"
adaptive_response_allowed: True
# Web聊天升级
connection web:
escalation_message: "正在为你转接人工客服。"
outbound_route_type: "OmniChannelFlow"
outbound_route_name: "<flow://Web_Chat_Escalation>"关键属性:
| 属性 | 是否必填 | 描述 |
|---|---|---|
| ✅ | 移交过程中向用户显示的消息 |
| ✅ | |
| ✅ | Flow API名称或队列名称 |
| ❌ | 允许LLM调整升级消息 |
🔄 WORKFLOW: Agent Development Lifecycle
🔄 工作流:智能体开发生命周期
Phase 1: Requirements & Design
阶段1:需求与设计
- Identify deterministic vs. subjective logic
- Deterministic: Security checks, financial thresholds, data lookups, counters
- Subjective: Greetings, context understanding, natural language generation
- Design FSM architecture - Map topics as states, transitions as edges
- Define variables - Mutable for state tracking, linked for session context
- 区分确定性与主观逻辑
- 确定性:安全检查、财务阈值、数据查询、计数器
- 主观:问候语、上下文理解、自然语言生成
- 设计FSM架构 - 将主题映射为状态,转换映射为边
- 定义变量 - 可变变量用于状态跟踪,关联变量用于会话上下文
Phase 2: Agent Script Authoring
阶段2:Agent Script编写
- Create file with required blocks
.agent - Write topics with instruction resolution pattern:
- Post-action checks at TOP (triggers on loop)
- Pre-LLM data loading
- Dynamic instructions for LLM
- Configure actions with appropriate target protocols
- Add guards to enforce security
available when
- 创建文件,包含必填块
.agent - 编写主题,使用指令解析模式:
- 动作后检查放在顶部(循环时触发)
- LLM处理前加载数据
- 为LLM提供动态指令
- 配置动作,使用合适的目标协议
- 添加保护,强化安全性
available when
Phase 3: Validation (LSP + CLI)
阶段3:验证(LSP + CLI)
AUTOMATIC: LSP validation runs on every Write/Edit tofiles. Errors are reported with line numbers and autofix suggestions..agent
自动执行:每次写入/编辑文件时,LSP验证会自动运行。错误会附带行号和自动修复建议。.agent
LSP Validation Loop (Find Error → Autofix)
LSP验证循环(发现错误 → 自动修复)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Write/Edit │ ──▶ │ LSP Analyze │ ──▶ │ Report │
│ .agent file │ │ (automatic) │ │ Errors │
└─────────────┘ └─────────────┘ └──────┬──────┘
│
┌────────────────────────────────────────┘
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Claude │ ──▶ │ Apply Fix │ ──▶ │ Re-validate │
│ Suggests Fix│ │ (Edit tool) │ │ (loop) │
└─────────────┘ └─────────────┘ └─────────────┘┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 写入/编辑 │ ──▶ │ LSP分析 │ ──▶ │ 报告错误 │
│ .agent文件 │ │ (自动) │ │ │
└─────────────┘ └─────────────┘ └──────┬──────┘
│
┌────────────────────────────────────────┘
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Claude建议 │ ──▶ │ 应用修复 │ ──▶ │ 重新验证 │
│ 修复方案 │ │ (编辑工具) │ │ (循环) │
└─────────────┘ └─────────────┘ └─────────────┘LSP Checks (Automatic)
LSP自动检查项
| Check | Severity | Autofix |
|---|---|---|
| Mixed tabs/spaces | ❌ Error | Convert to consistent spacing |
Lowercase booleans ( | ❌ Error | Capitalize to |
| Missing required blocks | ❌ Error | Add missing block template |
Missing | ❌ Error | Add placeholder with comment |
| Mutable + linked conflict | ❌ Error | Remove conflicting modifier |
| Undefined topic references | ⚠️ Warning | Create topic stub |
| Post-action check position | ⚠️ Warning | Move to top of instructions |
| 检查项 | 严重程度 | 是否支持自动修复 |
|---|---|---|
| 混合制表符和空格 | ❌ 错误 | 转换为一致的缩进方式 |
小写布尔值( | ❌ 错误 | 转换为大写 |
| 缺失必填块 | ❌ 错误 | 添加缺失块模板 |
缺失 | ❌ 错误 | 添加带注释的占位符 |
| mutable与linked冲突 | ❌ 错误 | 移除冲突修饰符 |
| 未定义的主题引用 | ⚠️ 警告 | 创建主题占位符 |
| 动作后检查位置错误 | ⚠️ 警告 | 移至指令顶部 |
CLI Validation (Before Deploy)
CLI验证(部署前)
bash
undefinedbash
undefinedValidate authoring bundle syntax
验证创作包语法
sf agent validate authoring-bundle --api-name MyAgent -o TARGET_ORG
undefinedsf agent validate authoring-bundle --api-name MyAgent -o TARGET_ORG
undefinedManual Checks
手动检查项
- exists and is active Einstein Agent User
default_agent_user - All topic references resolve to existing topics
- Action targets (,
flow://, etc.) exist in orgapex://
- 是存在且激活的Einstein Agent用户
default_agent_user - 所有主题引用指向已存在的主题
- 动作目标(、
flow://等)在组织中存在apex://
Phase 4: Testing (Delegate to /sf-ai-agentforce-testing
)
/sf-ai-agentforce-testing阶段4:测试(委托给/sf-ai-agentforce-testing
)
/sf-ai-agentforce-testing- Batch testing - Run up to 100 test cases simultaneously
- Quality metrics - Completeness, Coherence, Topic/Action Assertions
- LLM-as-Judge - Automated scoring against golden responses
- 批量测试 - 同时运行多达100个测试用例
- 质量指标 - 完整性、连贯性、主题/动作断言
- LLM作为评判者 - 自动与标准响应对比评分
Phase 5: Deployment
阶段5:部署
⚠️ CRITICAL: Use, NOTsf agent publish authoring-bundlesf project deploy start
- Create bundle directory:
force-app/main/default/aiAuthoringBundles/AgentName/ - Add files:
- - Your Agent Script
AgentName.agent - - Metadata XML (NOT
AgentName.bundle-meta.xml).aiAuthoringBundle-meta.xml
- Publish:
sf agent publish authoring-bundle --api-name AgentName -o TARGET_ORG - Monitor - Use trace debugging for production issues
⚠️ 关键提示:使用,不要使用sf agent publish authoring-bundlesf project deploy start
- 创建包目录:
force-app/main/default/aiAuthoringBundles/AgentName/ - 添加文件:
- - 你的Agent Script
AgentName.agent - - 元数据XML(不要使用
AgentName.bundle-meta.xml).aiAuthoringBundle-meta.xml
- 发布:
sf agent publish authoring-bundle --api-name AgentName -o TARGET_ORG - 监控 - 使用跟踪调试生产环境问题
Phase 5.5: API Channel Enablement (For Agent Runtime API Testing)
阶段5.5:API渠道启用(用于Agent Runtime API测试)
⚠️ Without these steps, Agent Runtime API calls return.500 Internal Server Error
After publishing an Agent Script agent, the following metadata must be configured for API access:
1. GenAiPlannerBundle — Add block:
plannerSurfacesWhen deploying via the pseudo metadata type, retrieve and verify the XML includes:
AgentGenAiPlannerBundlexml
<GenAiPlannerBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- ... existing elements ... -->
<plannerSurfaces>
<plannerSurface>
<surfaceType>EinsteinAgentApiChannel</surfaceType>
</plannerSurface>
</plannerSurfaces>
</GenAiPlannerBundle>If missing, add it and redeploy:
bash
sf project deploy start --metadata GenAiPlannerBundle:AgentName_Planner -o TARGET_ORG2. BotVersion — Set to :
surfacesEnabledtrueThe metadata defaults to . Update:
BotVersionsurfacesEnabledfalsexml
<BotVersion xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- ... existing elements ... -->
<surfacesEnabled>true</surfacesEnabled>
</BotVersion>bash
sf project deploy start --metadata BotVersion:AgentName.v1 -o TARGET_ORG3. External Client App (ECA) — Required for Client Credentials flow:
The Agent Runtime API requires OAuth with , , and scopes. See for ECA creation.
chatbot_apisfap_apiapi/sf-connected-appsNote: If you only need interactive testing via, skip ECA setup — preview uses standard org auth (sf agent preview, v2.121.7+).sf org login web
Validation — Confirm API access works:
bash
undefined⚠️ 未完成此步骤,Agent Runtime API调用会返回。500 Internal Server Error
发布Agent Script智能体后,必须配置以下元数据以支持API访问:
1. GenAiPlannerBundle — 添加块:
plannerSurfaces当通过伪元数据类型部署时,检索并验证XML包含:
AgentGenAiPlannerBundlexml
<GenAiPlannerBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- ... 现有元素 ... -->
<plannerSurfaces>
<plannerSurface>
<surfaceType>EinsteinAgentApiChannel</surfaceType>
</plannerSurface>
</plannerSurfaces>
</GenAiPlannerBundle>如果缺失,添加后重新部署:
bash
sf project deploy start --metadata GenAiPlannerBundle:AgentName_Planner -o TARGET_ORG2. BotVersion — 设置为:
surfacesEnabledtrueBotVersionsurfacesEnabledfalsexml
<BotVersion xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- ... 现有元素 ... -->
<surfacesEnabled>true</surfacesEnabled>
</BotVersion>bash
sf project deploy start --metadata BotVersion:AgentName.v1 -o TARGET_ORG3. 外部客户端应用(ECA) — 客户端凭证流必填:
Agent Runtime API需要带有、和权限的OAuth。创建ECA请查看。
chatbot_apisfap_apiapi/sf-connected-apps注意: 如果仅需要通过进行交互式测试,可跳过ECA设置 — 预览使用标准组织认证(sf agent preview,v2.121.7+)。sf org login web
验证 — 确认API访问正常:
bash
undefinedAcquire token
获取令牌
curl -X POST "https://YOUR_DOMAIN.my.salesforce.com/services/oauth2/token"
-d "grant_type=client_credentials&client_id=KEY&client_secret=SECRET"
-d "grant_type=client_credentials&client_id=KEY&client_secret=SECRET"
curl -X POST "https://YOUR_DOMAIN.my.salesforce.com/services/oauth2/token" \
-d "grant_type=client_credentials&client_id=KEY&client_secret=SECRET"
Create agent session
创建智能体会话
curl -X POST "https://YOUR_DOMAIN.my.salesforce.com/einstein/ai-agent/v1"
-H "Authorization: Bearer TOKEN"
-H "Content-Type: application/json"
-d '{"agentDefinitionId":"0XxXXXXXXXXXXXXXXX"}'
-H "Authorization: Bearer TOKEN"
-H "Content-Type: application/json"
-d '{"agentDefinitionId":"0XxXXXXXXXXXXXXXXX"}'
> **Symptom**: 500 error with `"errorCode": "UNKNOWN_EXCEPTION"` → Missing `plannerSurfaces` or `surfacesEnabled=false`.curl -X POST "https://YOUR_DOMAIN.my.salesforce.com/einstein/ai-agent/v1" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"agentDefinitionId":"0XxXXXXXXXXXXXXXXX"}'
> **症状**:500错误,附带`"errorCode": "UNKNOWN_EXCEPTION"` → 缺失`plannerSurfaces`或`surfacesEnabled=false`。Phase 6: CLI Operations
阶段6:CLI操作
bash
undefinedbash
undefinedRetrieve from org
从组织拉取
sf agent retrieve --name MyAgent --target-org sandbox
sf agent retrieve --name MyAgent --target-org sandbox
Validate syntax
验证语法
sf agent validate authoring-bundle --api-name MyAgent -o TARGET_ORG
sf agent validate authoring-bundle --api-name MyAgent -o TARGET_ORG
Publish to org (NOT sf project deploy!)
发布到组织(不要用sf project deploy!)
sf agent publish authoring-bundle --api-name MyAgent -o TARGET_ORG
sf agent publish authoring-bundle --api-name MyAgent -o TARGET_ORG
Publish without retrieving metadata (CI/CD optimization, v2.122.6+)
不检索元数据发布(CI/CD优化,v2.122.6+)
sf agent publish authoring-bundle --api-name MyAgent --skip-retrieve -o TARGET_ORG
sf agent publish authoring-bundle --api-name MyAgent --skip-retrieve -o TARGET_ORG
Generate authoring bundle scaffolding
生成创作包脚手架
sf agent generate authoring-bundle --api-name MyAgent -o TARGET_ORG
sf agent generate authoring-bundle --api-name MyAgent -o TARGET_ORG
Generate without retrieving from org (useful for CI/CD)
不从组织检索生成(适用于CI/CD)
sf agent generate authoring-bundle --api-name MyAgent --skip-retrieve -o TARGET_ORG
undefinedsf agent generate authoring-bundle --api-name MyAgent --skip-retrieve -o TARGET_ORG
undefinedBundle Structure (CRITICAL)
包结构(关键)
force-app/main/default/aiAuthoringBundles/
└── MyAgent/
├── MyAgent.agent # Agent Script file
└── MyAgent.bundle-meta.xml # NOT .aiAuthoringBundle-meta.xml!bundle-meta.xml content:
xml
<?xml version="1.0" encoding="UTF-8"?>
<AiAuthoringBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<bundleType>AGENT</bundleType>
</AiAuthoringBundle>force-app/main/default/aiAuthoringBundles/
└── MyAgent/
├── MyAgent.agent # Agent Script文件
└── MyAgent.bundle-meta.xml # 不要用.aiAuthoringBundle-meta.xml!bundle-meta.xml内容:
xml
<?xml version="1.0" encoding="UTF-8"?>
<AiAuthoringBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<bundleType>AGENT</bundleType>
</AiAuthoringBundle>📊 SCORING SYSTEM (100 Points)
📊 评分系统(100分)
Categories
分类
| Category | Points | Key Criteria |
|---|---|---|
| Structure & Syntax | 20 | Block ordering, indentation consistency, required fields present |
| Deterministic Logic | 25 | Security via |
| Instruction Resolution | 20 | Correct use of |
| FSM Architecture | 15 | Clear topic separation, explicit transitions, state management |
| Action Configuration | 10 | Correct protocols, input/output mapping, error handling |
| Deployment Readiness | 10 | Valid |
| 分类 | 分值 | 关键标准 |
|---|---|---|
| 结构与语法 | 20 | 块顺序、缩进一致性、必填字段存在性 |
| 确定性逻辑 | 25 | 通过 |
| 指令解析 | 20 | 正确使用 |
| FSM架构 | 15 | 清晰的主题分离、明确的转换、状态管理 |
| 动作配置 | 10 | 正确的协议、输入/输出映射、错误处理 |
| 部署就绪性 | 10 | 有效的 |
Scoring Rubric Details
评分细则
Structure & Syntax (20 points)
结构与语法(20分)
| Points | Criteria |
|---|---|
| 20 | All required blocks present, consistent indentation, valid identifiers |
| 15 | Minor issues (e.g., inconsistent spacing within tolerance) |
| 10 | Missing optional blocks that would improve clarity |
| 5 | Block ordering issues or mixed indentation |
| 0 | Missing required blocks or compilation failures |
| 分值 | 标准 |
|---|---|
| 20 | 所有必填块存在,缩进一致,标识符有效 |
| 15 | minor问题(例如,缩进不一致但在可接受范围内) |
| 10 | 缺失可提升清晰度的可选块 |
| 5 | 块顺序错误或混合缩进 |
| 0 | 缺失必填块或编译失败 |
Deterministic Logic (25 points)
确定性逻辑(25分)
| Points | Criteria |
|---|---|
| 25 | All security actions guarded with |
| 20 | Most guards present, minor gaps in deterministic enforcement |
| 15 | Some security logic relies on prompts instead of guards |
| 10 | Critical actions lack |
| 0 | Security logic entirely prompt-based (LLM can bypass) |
| 分值 | 标准 |
|---|---|
| 25 | 所有安全动作均有 |
| 20 | 大部分保护存在,确定性执行存在 minor 漏洞 |
| 15 | 部分安全逻辑依赖提示而非保护 |
| 10 | 关键动作缺失 |
| 0 | 安全逻辑完全基于提示(LLM可绕过) |
Instruction Resolution (20 points)
指令解析(20分)
| Points | Criteria |
|---|---|
| 20 | Arrow syntax for complex logic, proper template injection, correct action execution |
| 15 | Mostly correct, minor syntax issues |
| 10 | Uses pipe syntax where arrow needed, template injection errors |
| 5 | Incorrect phase ordering (data loads after LLM sees instructions) |
| 0 | Fundamental misunderstanding of resolution order |
| 分值 | 标准 |
|---|---|
| 20 | 复杂逻辑使用箭头语法,模板注入正确,动作执行正确 |
| 15 | 大部分正确,存在 minor 语法问题 |
| 10 | 在需要箭头语法的地方使用了管道语法,模板注入错误 |
| 5 | 阶段顺序错误(LLM处理指令后才加载数据) |
| 0 | 对解析顺序存在根本性误解 |
FSM Architecture (15 points)
FSM架构(15分)
| Points | Criteria |
|---|---|
| 15 | Clear topic boundaries, explicit transitions, appropriate escalation paths |
| 12 | Good structure with minor redundancy |
| 9 | Topics too broad or transitions unclear |
| 5 | Monolithic topic handling multiple concerns |
| 0 | No topic separation, all logic in start_agent |
| 分值 | 标准 |
|---|---|
| 15 | 主题边界清晰,转换明确,升级路径合理 |
| 12 | 结构良好,存在 minor 冗余 |
| 9 | 主题过于宽泛或转换不明确 |
| 5 | 单体主题处理多个关注点 |
| 0 | 无主题分离,所有逻辑在start_agent中 |
Action Configuration (10 points)
动作配置(10分)
| Points | Criteria |
|---|---|
| 10 | Correct protocols, proper I/O mapping, descriptions present |
| 8 | Minor issues (missing descriptions) |
| 5 | Wrong protocol for use case |
| 2 | Input/output mapping errors |
| 0 | Actions don't compile |
| 分值 | 标准 |
|---|---|
| 10 | 协议正确,输入/输出映射正确,描述存在 |
| 8 | minor问题(缺失描述) |
| 5 | 协议与使用场景不匹配 |
| 2 | 输入/输出映射错误 |
| 0 | 动作无法编译 |
Deployment Readiness (10 points)
部署就绪性(10分)
| Points | Criteria |
|---|---|
| 10 | Valid user, clean validation, metadata complete |
| 8 | Minor warnings |
| 5 | Validation errors that need fixing |
| 2 | Missing metadata files |
| 0 | Cannot deploy |
| 分值 | 标准 |
|---|---|
| 10 | 用户有效,验证通过,元数据完整 |
| 8 | minor警告 |
| 5 | 存在需要修复的验证错误 |
| 2 | 缺失元数据文件 |
| 0 | 无法部署 |
Score Thresholds
分数阈值
| Score | Rating | Action |
|---|---|---|
| 90-100 | ⭐⭐⭐⭐⭐ Excellent | Deploy with confidence |
| 80-89 | ⭐⭐⭐⭐ Very Good | Minor improvements recommended |
| 70-79 | ⭐⭐⭐ Good | Review flagged issues before deploy |
| 60-69 | ⭐⭐ Needs Work | Address issues before deploy |
| <60 | ⭐ Critical | BLOCK - Fix critical issues |
| 分数 | 评级 | 操作建议 |
|---|---|---|
| 90-100 | ⭐⭐⭐⭐⭐ 优秀 | 放心部署 |
| 80-89 | ⭐⭐⭐⭐ 非常好 | 建议进行 minor 改进 |
| 70-79 | ⭐⭐⭐ 良好 | 部署前复查标记的问题 |
| 60-69 | ⭐⭐ 需要改进 | 部署前解决问题 |
| <60 | ⭐ 关键问题 | 阻止部署 - 修复关键问题 |
Score Report Format
评分报告格式
📊 AGENT SCRIPT SCORE REPORT
════════════════════════════════════════
Score: 85/100 ⭐⭐⭐⭐ Very Good
├─ Structure & Syntax: 18/20 (90%)
├─ Deterministic Logic: 22/25 (88%)
├─ Instruction Resolution: 16/20 (80%)
├─ FSM Architecture: 12/15 (80%)
├─ Action Configuration: 9/10 (90%)
└─ Deployment Readiness: 8/10 (80%)
Issues:
⚠️ [Deterministic] Missing `available when` on process_refund action
⚠️ [Resolution] Post-action check should be at TOP of instructions
✓ All Structure & Syntax checks passed
✓ All Action Configuration checks passed📊 AGENT SCRIPT评分报告
════════════════════════════════════════
分数: 85/100 ⭐⭐⭐⭐ 非常好
├─ 结构与语法: 18/20 (90%)
├─ 确定性逻辑: 22/25 (88%)
├─ 指令解析: 16/20 (80%)
├─ FSM架构: 12/15 (80%)
├─ 动作配置: 9/10 (90%)
└─ 部署就绪性: 8/10 (80%)
问题:
⚠️ [确定性逻辑] process_refund动作缺失`available when`保护
⚠️ [解析] 动作后检查应放在指令顶部
✓ 所有结构与语法检查通过
✓ 所有动作配置检查通过🔧 THE 6 DETERMINISTIC BUILDING BLOCKS
🔧 6个确定性构建块
These execute as code, not suggestions. The LLM cannot override them.
| # | Block | Description | Example |
|---|---|---|---|
| 1 | Conditionals | if/else resolves before LLM | |
| 2 | Topic Filters | Control action visibility | |
| 3 | Variable Checks | Numeric/boolean comparisons | |
| 4 | Inline Actions | Immediate execution | |
| 5 | Utility Actions | Built-in helpers | |
| 6 | Variable Injection | Template values | |
这些以代码形式执行,而非建议。LLM无法覆盖它们。
| 序号 | 块 | 描述 | 示例 |
|---|---|---|---|
| 1 | 条件判断 | if/else在LLM处理前解析 | |
| 2 | 主题过滤器 | 控制动作可见性 | |
| 3 | 变量检查 | 数值/布尔值比较 | |
| 4 | 内联动作 | 立即执行 | |
| 5 | 工具动作 | 内置助手 | |
| 6 | 变量注入 | 模板值 | |
📐 ARCHITECTURE PATTERNS
📐 架构模式
Pattern 1: Hub and Spoke
模式1:中心辐射式
Central router (hub) to specialized topics (spokes). Use for multi-purpose agents.
┌─────────────┐
│ topic_sel │
│ (hub) │
└──────┬──────┘
┌─────────┼─────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│refunds │ │ orders │ │support │
└────────┘ └────────┘ └────────┘中心路由器(中心)连接到专用主题(辐射)。适用于多用途智能体。
┌─────────────┐
│ topic_sel │
│ (中心) │
└──────┬──────┘
┌─────────┼─────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│退款 │ │订单 │ │支持 │
└────────┘ └────────┘ └────────┘Pattern 2: Verification Gate
模式2:验证网关
Security gate before protected topics. Mandatory for sensitive data.
┌─────────┐ ┌──────────┐ ┌───────────┐
│ entry │ ──▶ │ VERIFY │ ──▶ │ protected │
└─────────┘ │ (GATE) │ │ topics │
└────┬─────┘ └───────────┘
│ 3 fails
▼
┌──────────┐
│ lockout │
└──────────┘受保护主题前的安全网关。敏感数据场景必填。
┌─────────┐ ┌──────────┐ ┌───────────┐
│ 入口 │ ──▶ │ 验证 │ ──▶ │ 受保护主题 │
└─────────┘ │ (网关) │ │ │
└────┬─────┘ └───────────┘
│ 3次失败
▼
┌──────────┐
│ 锁定 │
└──────────┘Pattern 3: Post-Action Loop
模式3:动作后循环
Topic re-resolves after action completes - put checks at TOP.
yaml
topic refund:
reasoning:
instructions: ->
# POST-ACTION CHECK (at TOP - triggers on next loop)
if @variables.refund_status == "Approved":
run @actions.create_crm_case
transition to @topic.success
# PRE-LLM DATA LOADING
run @actions.check_churn_risk
set @variables.risk = @outputs.score
# DYNAMIC INSTRUCTIONS FOR LLM
if @variables.risk >= 80:
| Offer full refund to retain customer.
else:
| Offer $10 credit instead.动作完成后主题重新解析 - 检查放在顶部。
yaml
topic refund:
reasoning:
instructions: ->
# 动作后检查(放在顶部 - 下一次循环时触发)
if @variables.refund_status == "Approved":
run @actions.create_crm_case
transition to @topic.success
# LLM处理前加载数据
run @actions.check_churn_risk
set @variables.risk = @outputs.score
# 为LLM提供动态指令
if @variables.risk >= 80:
| 提供全额退款以挽留客户。
else:
| 提供10美元信用额度替代。🐛 DEBUGGING: Trace Analysis
🐛 调试:跟踪分析
The 6 Span Types
6种跟踪类型
| Span | Description |
|---|---|
➡️ | Execution enters a topic |
▶ | Deterministic pre-processing |
🧠 | LLM processes instructions |
⚡ | Action invoked |
→ | Topic navigation |
✓ | Deterministic post-processing |
| 跟踪类型 | 描述 |
|---|---|
➡️ | 执行进入主题 |
▶ | 确定性预处理 |
🧠 | LLM处理指令 |
⚡ | 动作被调用 |
→ | 主题导航 |
✓ | 确定性后处理 |
Debugging Workflow
调试工作流
- Interaction Details - Quick understanding of what happened
- Trace Waterfall - Technical view with exact prompts, latencies
- Variable State - Entry vs Exit values reveal when state was ignored
- Script View - Red squiggles show syntax errors
- 交互详情 - 快速了解发生了什么
- 跟踪瀑布图 - 包含准确提示、延迟的技术视图
- 变量状态 - 入口与出口值揭示状态何时被忽略
- 脚本视图 - 红色波浪线显示语法错误
Common Debug Patterns
常见调试模式
| Symptom | Check | Fix |
|---|---|---|
| Wrong policy applied | Variable Entry values | Change |
| Action executed without auth | | Add guard clause |
| LLM ignores variable | Instruction resolution order | Move data load before LLM text |
| Infinite loop | Transition conditions | Add exit condition |
| 症状 | 检查项 | 修复方法 |
|---|---|---|
| 应用了错误的策略 | 变量入口值 | 将 |
| 动作未授权即执行 | | 添加保护子句 |
| LLM忽略变量 | 指令解析顺序 | 将数据加载移至LLM文本之前 |
| 无限循环 | 转换条件 | 添加退出条件 |
⚠️ COMMON ISSUES & FIXES
⚠️ 常见问题与修复
| Issue | Symptom | Fix |
|---|---|---|
| Invalid | Query: |
| User doesn't exist in target org | Query the specific target org (user formats vary: some use |
| | Make |
| Mixed indentation | Use consistent spacing throughout |
| Nested if statements | Use compound condition: |
| Top-level actions block | Move actions inside |
| | Use |
| | Use |
| | Use Helper Topic Pattern (set in |
| Multiple guards on action | Combine: |
| Reserved action name | Rename to |
| Typo in topic reference | Check spelling, ensure topic exists |
| Conflicting modifiers | Choose one: mutable for state, linked for external |
| Using wrong deploy command | Use |
| Wrong file naming | Rename to |
| Action not defined in topic | Define action in topic-level |
| LLM bypasses security check | Using prompts for security | Use |
| Post-action logic doesn't run | Check not at TOP | Move post-action check to first lines |
| Wrong data retrieved | Missing filter | Wrap retriever in Flow with filter inputs |
| Variables don't change | Using | Post-action |
| Wrong target protocol | | Remove trailing |
| Prompt template input not mapped | Unquoted | Quote it: |
| Missing type on action input | | Add type: |
| 问题 | 症状 | 修复方法 |
|---|---|---|
| | 查询: |
| 用户在目标组织中不存在 | 专门查询目标组织(用户格式因组织而异:部分使用 |
| | 使 |
| 混合缩进 | 全程使用一致的缩进方式 |
| 嵌套if语句 | 使用复合条件: |
| 顶层actions块 | 将actions移至 |
| 动作内的 | 使用 |
| 动作内的 | 使用 |
| | 使用辅助主题模式(在 |
| 动作有多个保护 | 合并为: |
| 使用了保留动作名称 | 重命名为 |
| 主题引用拼写错误 | 检查拼写,确保主题存在 |
| 修饰符冲突 | 选择其一:可变变量用于状态,关联变量用于外部数据 |
| 使用了错误的部署命令 | 使用 |
| 文件命名错误 | 重命名为 |
| 动作未在主题 | 在主题级 |
| LLM绕过安全检查 | 使用提示实现安全 | 使用 |
| 动作后逻辑未执行 | 检查未放在顶部 | 将动作后检查移至第一行 |
| 获取了错误的数据 | 缺失过滤器 | 在Flow中包装检索器并添加过滤输入 |
| 变量未更改 | 对 | 动作后 |
| 目标协议错误 | | 移除末尾的 |
| 提示模板输入未映射 | | 添加引号: |
| 动作输入缺失类型 | | 添加类型: |
Deployment Gotchas (Validated by Testing)
部署注意事项(经测试验证)
| ❌ Wrong | ✅ Correct |
|---|---|
| |
| |
| |
| Query user from wrong org | Query target org specifically with |
| ❌ 错误操作 | ✅ 正确操作 |
|---|---|
| |
| |
| |
| 从错误的组织查询用户 | 使用 |
Einstein Agent User Format (Org-Specific)
Einstein Agent用户格式(组织特定)
Einstein Agent User formats vary between orgs:
- Production/Partner orgs: Often use format (e.g.,
username@orgid.ext)resort_manager@00dak00000gdgwu480119933.ext - Dev orgs: May use format
username.suffix@orgfarm.salesforce.com
MANDATORY: Ask user to confirm which Einstein Agent User to use when creating a new agent.
Always query the specific target org:
bash
undefinedEinstein Agent用户格式因组织而异:
- 生产/合作伙伴组织:通常使用格式(例如
username@orgid.ext)resort_manager@00dak00000gdgwu480119933.ext - 开发组织:可能使用格式
username.suffix@orgfarm.salesforce.com
必填操作:创建新智能体时,要求用户确认使用哪个Einstein Agent用户。
务必专门查询目标组织:
bash
undefinedQuery target org specifically
专门查询目标组织
sf data query -q "SELECT Username FROM User WHERE Profile.Name = 'Einstein Agent User' AND IsActive = true" -o YOUR_TARGET_ORG
Present the results to the user and ask them to select which user to use for `default_agent_user`.
> ⚠️ A user existing in one org does NOT mean it exists in another. Always verify in the deployment target.
---sf data query -q "SELECT Username FROM User WHERE Profile.Name = 'Einstein Agent User' AND IsActive = true" -o YOUR_TARGET_ORG
将结果展示给用户,让他们选择用于`default_agent_user`的用户。
> ⚠️ 一个组织中的用户**不代表**在另一个组织中存在。部署前务必在目标组织中验证。
---📚 DOCUMENT MAP (Progressive Disclosure)
📚 文档地图(渐进式披露)
Tier 2: Resource Guides (Comprehensive)
第二层级:资源指南(全面)
| Need | Document | Description |
|---|---|---|
| Syntax reference | resources/syntax-reference.md | Complete block & expression syntax |
| FSM design | resources/fsm-architecture.md | State machine patterns & examples |
| Instruction resolution | resources/instruction-resolution.md | Three-phase execution model |
| Data & multi-agent | resources/grounding-multiagent.md | Retriever actions & SOMA patterns |
| Debugging | resources/debugging-guide.md | Trace analysis & forensics |
| Testing | resources/testing-guide.md | Batch testing & quality metrics |
| Prompt template actions | resources/action-prompt-templates.md | |
| Advanced action patterns | resources/action-patterns.md | Context-aware descriptions, |
| Actions reference | resources/actions-reference.md | Complete action types, GenAiFunction metadata, escalation routing, Flow/Apex/API patterns |
| 需求 | 文档 | 描述 |
|---|---|---|
| 语法参考 | resources/syntax-reference.md | 完整的块与表达式语法 |
| FSM设计 | resources/fsm-architecture.md | 状态机模式与示例 |
| 指令解析 | resources/instruction-resolution.md | 三阶段执行模型 |
| 数据与多智能体 | resources/grounding-multiagent.md | 检索器动作与SOMA模式 |
| 调试 | resources/debugging-guide.md | 跟踪分析与取证 |
| 测试 | resources/testing-guide.md | 批量测试与质量指标 |
| 提示模板动作 | resources/action-prompt-templates.md | |
| 高级动作模式 | resources/action-patterns.md | 上下文感知描述、 |
| 动作参考 | resources/actions-reference.md | 完整的动作类型、GenAiFunction元数据、升级路由、Flow/Apex/API模式 |
Tier 3: Quick References (Docs)
第三层级:快速参考(文档)
| Need | Document | Description |
|---|---|---|
| CLI commands | docs/cli-guide.md | sf agent retrieve/validate/deploy |
| Patterns | docs/patterns-quick-ref.md | Decision tree for pattern selection |
| 需求 | 文档 | 描述 |
|---|---|---|
| CLI命令 | docs/cli-guide.md | sf agent拉取/验证/部署 |
| 模式 | docs/patterns-quick-ref.md | 模式选择决策树 |
Tier 4: Templates
第四层级:模板
| Category | Directory | Contents |
|---|---|---|
| Root templates | templates/ | 7 .agent templates (minimal-starter, hub-and-spoke, etc.) |
| Complete agents | templates/agents/ | 4 full agent examples (hello-world, simple-qa, multi-topic, production-faq) |
| Components | templates/components/ | 6 component fragments (apex-action, error-handling, escalation, flow-action, n-ary-conditions, topic-with-actions) |
| Advanced patterns | templates/patterns/ | 11 pattern templates (action-callbacks, bidirectional-routing, delegation, lifecycle-events, etc.) |
| Metadata XML | templates/metadata/ | 6 XML templates (GenAiFunction, GenAiPlugin, PromptTemplate, Flow) |
| Apex | templates/apex/ | Models API queueable class |
| 分类 | 目录 | 内容 |
|---|---|---|
| 根模板 | templates/ | 7个.agent模板(最小启动模板、中心辐射式等) |
| 完整智能体 | templates/agents/ | 4个完整智能体示例(Hello World、简单问答、多主题、生产环境FAQ) |
| 组件 | templates/components/ | 6个组件片段(Apex动作、错误处理、升级、Flow动作、多条件、带动作的主题) |
| 高级模式 | templates/patterns/ | 11个模式模板(动作回调、双向路由、委托、生命周期事件等) |
| 元数据XML | templates/metadata/ | 6个XML模板(GenAiFunction、GenAiPlugin、PromptTemplate、Flow) |
| Apex | templates/apex/ | Models API队列类 |
🔗 CROSS-SKILL INTEGRATION
🔗 跨技能集成
MANDATORY Delegations
必须委托的任务
| Task | Delegate To | Reason |
|---|---|---|
Create Flows for | | Flows must exist before agent uses them |
| Test agent routing & actions | | Specialized testing patterns |
| Deploy agent to org | | Proper deployment validation |
| 任务 | 委托给 | 原因 |
|---|---|---|
为 | | 智能体使用前必须存在Flow |
| 测试智能体路由与动作 | | 专用测试模式 |
| 将智能体部署到组织 | | 正确的部署验证 |
Integration Patterns
集成模式
| From | To | Pattern |
|---|---|---|
| | Create Flow, then reference in agent |
| | Create Apex class with |
| | Set up Named Credentials for |
| 来源 | 目标 | 模式 |
|---|---|---|
| | 创建Flow,然后在智能体中引用 |
| | 创建带 |
| | 为 |
✅ DEPLOYMENT CHECKLIST
✅ 部署检查清单
Configuration
配置
- is valid Einstein Agent User
default_agent_user - uses snake_case (no spaces)
agent_name
- 是有效的Einstein Agent用户
default_agent_user - 使用蛇形命名法(无空格)
agent_name
Syntax
语法
- No mixed tabs/spaces
- Booleans use /
TrueFalse - Variable names use snake_case
- 未混合使用制表符和空格
- 布尔值使用/
TrueFalse - 变量名使用蛇形命名法
Structure
结构
- Exactly one block
start_agent - At least one block
topic - All transitions reference existing topics
- 仅存在一个块
start_agent - 至少存在一个块
topic - 所有转换引用已存在的主题
Security
安全
- Critical actions have guards
available when - Session data uses variables (not
linked)mutable
- 关键动作有保护
available when - 会话数据使用变量(而非
linked)mutable
Testing
测试
- passes
sf agent validate --source-dir ./my-agent - Preview mode tested before activation
- 通过
sf agent validate --source-dir ./my-agent - 部署前已在预览模式中测试
🚀 MINIMAL WORKING EXAMPLE
🚀 最小可用示例
yaml
config:
developer_name: "simple_agent"
agent_description: "A minimal working agent example"
agent_type: "AgentforceServiceAgent" # or "AgentforceEmployeeAgent"
default_agent_user: "agent_user@yourorg.com"
system:
messages:
welcome: "Hello! How can I help you today?"
error: "Sorry, something went wrong."
instructions: "You are a helpful customer service agent."
variables:
customer_verified: mutable boolean = False
topic main:
description: "Main conversation handler"
reasoning:
instructions: ->
if @variables.customer_verified == True:
| You are speaking with a verified customer.
| Help them with their request.
else:
| Please verify the customer's identity first.
actions:
verify: @actions.verify_customer
description: "Verify customer identity"
set @variables.customer_verified = @outputs.verified
start_agent entry:
description: "Entry point for all conversations"
reasoning:
instructions: |
Greet the customer and route to the main topic.
actions:
go_main: @utils.transition to @topic.main
description: "Navigate to main conversation"yaml
config:
developer_name: "simple_agent"
agent_description: "最小可用智能体示例"
agent_type: "AgentforceServiceAgent" # 或"AgentforceEmployeeAgent"
default_agent_user: "agent_user@yourorg.com"
system:
messages:
welcome: "你好!今天我能为你提供什么帮助?"
error: "抱歉,出现了一些问题。"
instructions: "你是一个乐于助人的客户服务智能体。"
variables:
customer_verified: mutable boolean = False
topic main:
description: "主对话处理"
reasoning:
instructions: ->
if @variables.customer_verified == True:
| 你正在与已验证客户对话。
| 请协助处理他们的请求。
else:
| 请先验证客户身份。
actions:
verify: @actions.verify_customer
description: "验证客户身份"
set @variables.customer_verified = @outputs.verified
start_agent entry:
description: "所有对话的入口点"
reasoning:
instructions: |
问候客户并路由到主主题。
actions:
go_main: @utils.transition to @topic.main
description: "导航到主对话"📖 OFFICIAL RESOURCES
📖 官方资源
📚 SOURCES & ACKNOWLEDGMENTS
📚 来源与致谢
This skill draws from multiple authoritative sources:
| Source | Contribution |
|---|---|
| trailheadapps/agent-script-recipes | 20 reference recipes across 4 categories, AGENT_SCRIPT.md rules document, variable patterns, action target catalog |
| Salesforce Official Documentation | Core syntax, API references, deployment guides |
| TDD Validation (this skill) | 13 validation agents confirming current-release syntax compatibility |
| Tribal knowledge interviews | Canvas View bugs, VS Code limitations, credit consumption patterns |
| agentforce.guide | Unofficial but useful examples (note: some patterns don't compile in current release) |
| @kunello (PR #20) | Prompt template |
⚠️ Note on Feature Validation: Some patterns from external sources (e.g.,,always_expect_input:property, certain action properties on transitions) do NOT compile in Winter '26. Thelabel:/before_reasoning:lifecycle hooks ARE valid but require direct content (noafter_reasoning:wrapper) - see the Lifecycle Hooks section for correct syntax. This skill documents only patterns that pass TDD validation.instructions:
本技能参考了多个权威来源:
| 来源 | 贡献 |
|---|---|
| trailheadapps/agent-script-recipes | 4个分类下的20个参考示例、AGENT_SCRIPT.md规则文档、变量模式、动作目标目录 |
| Salesforce官方文档 | 核心语法、API参考、部署指南 |
| 本技能的TDD验证 | 13个验证智能体,确认当前版本语法兼容性 |
| 行业经验访谈 | Canvas视图问题、VS Code限制、积分消耗模式 |
| agentforce.guide | 非官方但实用的示例(注意:部分模式在当前版本无法编译) |
| @kunello (PR #20) | 提示模板 |
⚠️ 功能验证说明:部分来自外部来源的模式(例如、always_expect_input:属性、转换动作的某些属性)在Winter '26版本中无法编译。label:/before_reasoning:生命周期钩子有效,但需要直接内容(无after_reasoning:包装器)- 请查看生命周期钩子部分的正确语法。本技能仅记录通过TDD验证的模式。instructions:
🏷️ VERSION HISTORY
🏷️ 版本历史
| Version | Date | Changes |
|---|---|---|
| 1.7.0 | 2026-02-09 | CRITICAL FIX: apex:// works directly, GenAiFunction NOT needed for Agent Script. Removed false "Known Issue" claiming |
| 1.6.0 | 2026-02-07 | Content migration from former sf-ai-agentforce-legacy: Migrated 28 template files across 5 categories (agents/, components/, patterns/, metadata/, apex/) from the former legacy skill (now |
| 1.5.0 | 2026-02-06 | Action patterns & prompt template docs (from @kunello PR #20): Added |
| 1.3.0 | 2026-01-20 | Lifecycle hooks validated: Added full documentation for |
| 1.2.0 | 2026-01-20 | Gap analysis vs agent-script-recipes: Expanded Action Target Protocols from 7 to 16 (with validation status indicators), added Variable vs Action I/O Type Matrix, added lifecycle hooks note with TDD validation caveat, added Sources & Acknowledgments section, documented future/planned features notice. TDD validation confirmed |
| 1.1.0 | 2026-01-20 | "Ultimate Guide" tribal knowledge integration: Added |
| 1.0.4 | 2026-01-19 | Progressive testing validation (Quiz_Master, Expense_Calculator, Order_Processor): Added constraints for no top-level |
| 1.0.3 | 2026-01-19 | Added Einstein Agent User interview requirement - mandatory user confirmation when creating new agents |
| 1.0.2 | 2026-01-19 | Major corrections from GitHub reference: Fixed block order (config→system), added Helper Topic Pattern, transition vs delegation, expression operators (+/- only), naming rules (80 char max), slot-filling |
| 1.0.1 | 2026-01-19 | Added syntax constraints from 0-shot testing: no nested if, one available when per action, reserved action names |
| 1.0.0 | 2026-01 | Initial release with 8-module coverage |
| 版本 | 日期 | 变更 |
|---|---|---|
| 1.7.0 | 2026-02-09 | 关键修复:apex://直接生效,Agent Script无需GenAiFunction。移除了声称 |
| 1.6.0 | 2026-02-07 | 从原sf-ai-agentforce-legacy迁移内容:从原旧技能(现为 |
| 1.5.0 | 2026-02-06 | 动作模式与提示模板文档(来自@kunello PR #20):添加 |
| 1.3.0 | 2026-01-20 | 生命周期钩子已验证:添加 |
| 1.2.0 | 2026-01-20 | 与agent-script-recipes的差距分析:将动作目标协议从7个扩展到16个(带验证状态指示器),添加变量与动作I/O类型矩阵,添加带TDD验证注意事项的生命周期钩子说明,添加来源与致谢部分,记录未来/计划功能通知。TDD验证确认 |
| 1.1.0 | 2026-01-20 | “终极指南”行业经验整合:添加 |
| 1.0.4 | 2026-01-19 | 渐进式测试验证(Quiz_Master、Expense_Calculator、Order_Processor):添加禁止顶层 |
| 1.0.3 | 2026-01-19 | 添加Einstein Agent用户访谈要求 - 创建新智能体时必须确认用户 |
| 1.0.2 | 2026-01-19 | GitHub参考文档的主要修正:修复块顺序(config→system),添加辅助主题模式、转换与委托、表达式运算符(仅+/-)、命名规则(最大80字符)、槽位填充 |
| 1.0.1 | 2026-01-19 | 添加0-shot测试得出的语法约束:禁止嵌套if、每个动作仅一个available when、保留动作名称 |
| 1.0.0 | 2026-01 | 初始版本,包含8个模块内容 |
| ", |