building-omnistudio-callable-apex
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesebuilding-omnistudio-callable-apex: Callable Apex for Salesforce Industries Common Core
building-omnistudio-callable-apex: 面向Salesforce Industries Common Core的Callable Apex
Specialist for Salesforce Industries Common Core callable Apex implementations. Produce secure,
deterministic, and configurable Apex that cleanly integrates with OmniStudio and Industries
extension points.
专注于Salesforce Industries Common Core的Callable Apex实现。生成安全、可预测且可配置的Apex代码,与OmniStudio及Industries扩展点实现无缝集成。
Scope
适用范围
- In scope: Creating classes for Industries extension points; reviewing callable implementations for correctness and risks; migrating
System.Callable/VlocityOpenInterfacetoVlocityOpenInterface2; 120-point scoring and validationSystem.Callable - Out of scope: Generic Apex classes without callable interface (use ); building Integration Procedures (use
generating-apex); authoring OmniScripts (usebuilding-omnistudio-integration-procedure); deploying Apex classes (usebuilding-omnistudio-omniscript)deploying-metadata
- 包含场景:为Industries扩展点创建类;评审可调用实现的正确性与风险;将
System.Callable/VlocityOpenInterface迁移至VlocityOpenInterface2;120分评分与验证System.Callable - 排除场景:无Callable接口的通用Apex类(请使用技能);构建集成流程(请使用
generating-apex技能);编写OmniScript(请使用building-omnistudio-integration-procedure技能);部署Apex类(请使用building-omnistudio-omniscript技能)deploying-metadata
Core Responsibilities
核心职责
- Callable Generation: Build classes with safe action dispatch
System.Callable - Callable Review: Audit existing callable implementations for correctness and risks
- Validation & Scoring: Evaluate against the 120-point rubric
- Industries Fit: Ensure compatibility with OmniStudio/Industries extension points
- 可调用类生成:构建具备安全动作分发机制的类
System.Callable - 可调用类评审:审核现有可调用实现的正确性与风险点
- 验证与评分:基于120分评估标准进行校验
- Industries适配性:确保与OmniStudio/Industries扩展点的兼容性
Workflow (4-Phase Pattern)
工作流程(四阶段模式)
Phase 1: Requirements Gathering
阶段1:需求收集
Ask for:
- Entry point (OmniScript, Integration Procedure, DataRaptor, or other Industries hook)
- Action names (strings passed into )
call - Input/output contract (required keys, types, and response shape)
- Data access needs (objects/fields, CRUD/FLS (Create/Read/Update/Delete and Field-Level Security) rules)
- Side effects (DML, callouts, async requirements)
Then:
- Scan for existing callable classes:
Glob: **/*Callable*.cls - Identify shared utilities or base classes used for Industries extensions
- Create a task list
需询问以下信息:
- 入口点(OmniScript、集成流程、DataRaptor或其他Industries钩子)
- 动作名称(传入方法的字符串)
call - 输入/输出契约(必填键、类型及响应结构)
- 数据访问需求(对象/字段、CRUD/FLS(创建/读取/更新/删除及字段级安全)规则)
- 副作用(DML操作、外部调用、异步需求)
完成询问后:
- 扫描现有可调用类:
Glob: **/*Callable*.cls - 识别用于Industries扩展的共享工具类或基类
- 创建任务清单
Phase 2: Design & Contract Definition
阶段2:设计与契约定义
Define the callable contract:
- Action list (explicit, versioned strings)
- Input schema (required keys + types)
- Output schema (consistent response envelope)
Recommended response envelope:
{
"success": true|false,
"data": {...},
"errors": [ { "code": "...", "message": "..." } ]
}Action dispatch rules:
- Use
switch on action - Default case throws a typed exception
- No dynamic method invocation or reflection
VlocityOpenInterface / VlocityOpenInterface2 contract mapping:
When designing for legacy Open Interface extensions (or dual Callable + Open Interface support), map the signature:
invokeMethod(String methodName, Map<String, Object> inputMap, Map<String, Object> outputMap, Map<String, Object> options)| Parameter | Role | Callable equivalent |
|---|---|---|
| Action selector (same semantics as | |
| Primary input data (required keys, types) | |
| Mutable map where results are written (out-by-reference) | Return value; Callable returns envelope instead |
| Additional context (parent DataRaptor/OmniScript context, invocation metadata) | |
Design rules for Open Interface contracts:
- Treat and
inputMapas the combined input schemaoptions - Define what keys must be written to per action (success and error cases)
outputMap - Preserve strings so they align with Callable
methodNamestringsaction - Document whether is required, optional, or unused for each action
options
定义可调用契约:
- 动作列表(明确的、带版本的字符串)
- 输入 schema(必填键 + 类型)
- 输出 schema(统一的响应信封)
推荐响应信封格式:
{
"success": true|false,
"data": {...},
"errors": [ { "code": "...", "message": "..." } ]
}动作分发规则:
- 使用语法
switch on action - 默认分支抛出类型化异常
- 禁止动态方法调用或反射
VlocityOpenInterface / VlocityOpenInterface2契约映射:
当为旧版Open Interface扩展设计(或同时支持Callable + Open Interface)时,需映射以下签名:
invokeMethod(String methodName, Map<String, Object> inputMap, Map<String, Object> outputMap, Map<String, Object> options)| 参数 | 作用 | Callable等效项 |
|---|---|---|
| 动作选择器(与 | |
| 主输入数据(必填键、类型) | |
| 写入结果的可变映射(按引用传递输出) | 返回值;Callable返回响应信封替代此方式 |
| 附加上下文(父级DataRaptor/OmniScript上下文、调用元数据) | |
Open Interface契约设计规则:
- 将和
inputMap视为组合输入schemaoptions - 定义每个动作需写入的键(成功与错误场景)
outputMap - 保留字符串,使其与Callable的
methodName字符串对齐action - 记录每个动作中是必填、可选还是未使用
options
Phase 3: Implementation Pattern
阶段3:实现模式
Vanilla System.Callable (flat args, no Open Interface coupling):
Read before generating — use when callers pass flat args and no VlocityOpenInterface integration is required.
assets/pattern_callable_vanilla.clsCallable skeleton (same inputs as VlocityOpenInterface):
Read before generating — use and keys in when integrating with Open Interface or when callers pass that structure.
assets/pattern_callable_openinterface.clsinputMapoptionsargsInput format: Callers pass as . For backward compatibility with flat callers, if lacks , treat itself as and use an empty map for .
args{ 'inputMap' => Map<String, Object>, 'options' => Map<String, Object> }args'inputMap'argsinputMapoptionsImplementation rules:
- Keep thin; delegate to private methods or service classes
call() - Validate and coerce input types early (null-safe)
- Enforce CRUD/FLS (Create/Read/Update/Delete and Field-Level Security) and sharing (,
with sharing)Security.stripInaccessible() - Bulkify when args include record collections
- Use for SOQL when appropriate
WITH USER_MODE - Namespace handling: is a standard interface (no namespace prefix required);
System.Callableuses the managedomnistudio.VlocityOpenInterface2package namespace — always qualify it. If the callable class will be deployed into a namespaced managed package, ask the user for the namespace prefix and apply it to custom class names (e.g.,omnistudio)myns__Industries_XxxCallable
VlocityOpenInterface / VlocityOpenInterface2 implementation:
When implementing or , use the signature:
omnistudio.VlocityOpenInterfaceomnistudio.VlocityOpenInterface2apex
global Boolean invokeMethod(String methodName, Map<String, Object> inputMap,
Map<String, Object> outputMap, Map<String, Object> options)Read before generating — complete skeleton with dispatch and contract.
assets/pattern_openinterface.clsVlocityOpenInterface2switch onoutputMapOpen Interface implementation rules:
- Write results into via
outputMapor individualputAll()calls; do not return the envelope fromput()invokeMethod - Return for success,
truefor unsupported or failed actionsfalse - Use the same internal private methods as the Callable (same and
inputMapparameters); only the entry point differsoptions - Populate with the same envelope shape (
outputMap,success,data) for consistencyerrors
Both Callable and Open Interface accept the same inputs (, ) and delegate to identical private method signatures for shared logic.
inputMapoptions原生System.Callable(扁平参数,无Open Interface耦合):
生成前请阅读 —— 适用于调用方传递扁平参数且无需集成VlocityOpenInterface的场景。
assets/pattern_callable_vanilla.cls兼容VlocityOpenInterface的Callable骨架:
生成前请阅读 —— 当集成Open Interface或调用方传递该结构时,在中使用和键。
assets/pattern_callable_openinterface.clsargsinputMapoptions输入格式:调用方传递的格式为。为兼容扁平参数的调用方,若不含,则将本身视为,并使用空映射作为。
args{ 'inputMap' => Map<String, Object>, 'options' => Map<String, Object> }args'inputMap'argsinputMapoptions实现规则:
- 保持方法简洁;将逻辑委托给私有方法或服务类
call() - 尽早验证并安全转换输入类型(空值安全)
- 强制执行CRUD/FLS(创建/读取/更新/删除及字段级安全)与共享规则(、
with sharing)Security.stripInaccessible() - 当参数包含记录集合时,实现批量处理
- 适当时在SOQL中使用
WITH USER_MODE - 命名空间处理:是标准接口(无需命名空间前缀);
System.Callable使用托管包omnistudio.VlocityOpenInterface2的命名空间 —— 必须添加前缀。若可调用类将部署到带命名空间的托管包中,请询问用户命名空间前缀并应用到自定义类名(例如omnistudio)myns__Industries_XxxCallable
VlocityOpenInterface / VlocityOpenInterface2实现:
实现或时,使用以下签名:
omnistudio.VlocityOpenInterfaceomnistudio.VlocityOpenInterface2apex
global Boolean invokeMethod(String methodName, Map<String, Object> inputMap,
Map<String, Object> outputMap, Map<String, Object> options)生成前请阅读 —— 完整的骨架,包含分发与契约。
assets/pattern_openinterface.clsVlocityOpenInterface2switch onoutputMapOpen Interface实现规则:
- 通过或单个
putAll()调用将结果写入put();不要从outputMap返回响应信封invokeMethod - 成功时返回,不支持或失败的动作返回
truefalse - 使用与Callable相同的内部私有方法(相同的和
inputMap参数);仅入口点不同options - 为保持一致性,在中填充相同的响应信封结构(
outputMap、success、data)errors
Callable与Open Interface接受相同的输入(、),并委托给相同签名的私有方法以实现逻辑共享。
inputMapoptionsPhase 4: Testing & Validation
阶段4:测试与验证
Minimum tests:
- Positive: Supported action executes successfully
- Negative: Unsupported action throws expected exception
- Contract: Missing/invalid inputs return error envelope
- Bulk: Handles list inputs without hitting limits
Read — complete test class skeleton (positive, negative, contract, bulk, and null-args cases) before generating tests.
assets/pattern_test_class.cls最低测试要求:
- 正向测试:支持的动作执行成功
- 反向测试:不支持的动作抛出预期异常
- 契约测试:缺失/无效输入返回错误信封
- 批量测试:处理列表输入且不触发限制
请阅读 —— 生成测试前需完成测试类骨架(包含正向、反向、契约、批量及空参数场景)
assets/pattern_test_class.clsMigration: VlocityOpenInterface to System.Callable
迁移:从VlocityOpenInterface到System.Callable
When modernizing Industries extensions, move or
implementations to and keep the
action contract stable.
VlocityOpenInterfaceVlocityOpenInterface2System.CallableGuidance:
- Preserve action names () as
methodNamestrings inactioncall() - Pass and
inputMapas keys inoptions:args{ 'inputMap' => inputMap, 'options' => options } - Return a consistent response envelope instead of mutating
outMap - Keep thin; delegate to the same internal methods with
call()signature(inputMap, options) - Add tests for each action and unsupported action
Read — annotated before/after migration example (VlocityOpenInterface2 → System.Callable) before starting migration work.
assets/pattern_migration.cls当对Industries扩展进行现代化改造时,将或实现迁移至并保持动作契约稳定。
VlocityOpenInterfaceVlocityOpenInterface2System.Callable迁移指南:
- 保留动作名称()作为
methodName中的call()字符串action - 将和
inputMap作为options中的键传递:args{ 'inputMap' => inputMap, 'options' => options } - 返回统一的响应信封,而非修改
outMap - 保持方法简洁;委托给相同签名的内部方法
call()(inputMap, options) - 为每个动作及不支持的动作添加测试
请阅读 —— 开始迁移前查看带注释的迁移示例(VlocityOpenInterface2 → System.Callable)
assets/pattern_migration.clsBest Practices (120-Point Scoring)
最佳实践(120分评分标准)
| Category | Points | Key Rules |
|---|---|---|
| Contract & Dispatch | 20 | Explicit action list; |
| Input Validation | 20 | Required keys validated; types coerced safely; null guards |
| Security | 20 | |
| Error Handling | 15 | Typed exceptions; consistent error envelope; no empty catch |
| Bulkification & Limits | 20 | No SOQL/DML in loops; supports list inputs |
| Testing | 15 | Positive/negative/contract/bulk tests |
| Documentation | 10 | ApexDoc ( |
Thresholds: ✅ 90+ (Ready) | ⚠️ 70-89 (Review) | ❌ <70 (Block)
| 类别 | 分值 | 核心规则 |
|---|---|---|
| 契约与分发 | 20 | 明确的动作列表;使用 |
| 输入验证 | 20 | 必填键校验;安全转换类型;空值防护 |
| 安全性 | 20 | |
| 错误处理 | 15 | 类型化异常;统一错误信封;禁止空catch块 |
| 批量处理与限制 | 20 | 循环中禁止SOQL/DML;支持列表输入 |
| 测试 | 15 | 正向/反向/契约/批量测试 |
| 文档 | 10 | 类及动作方法的ApexDoc( |
阈值:✅ 90+(就绪) | ⚠️ 70-89(需评审) | ❌ <70(需整改)
⛔ Guardrails (Mandatory)
⛔ 强制约束
Stop and ask the user if any of these would be introduced:
- Dynamic method execution based on user input (no reflection)
- SOQL/DML inside loops
- on callable classes
without sharing - Silent failures (empty catch, swallowed exceptions)
- Inconsistent response shapes across actions
若将引入以下任何情况,请停止操作并询问用户:
- 基于用户输入的动态方法执行(禁止反射)
- 循环内的SOQL/DML操作
- 可调用类使用
without sharing - 静默失败(空catch块、吞掉异常)
- 不同动作的响应结构不一致
Gotchas
常见陷阱
| Issue | Resolution |
|---|---|
Caller passes flat args but code expects | Guard defensively: if |
| Always null-check |
Test class uses | Ensure every action returns the same envelope type ( |
VlocityOpenInterface2 migration breaks callers that read | After migrating to Callable, callers must read the return value instead of reading |
| This custom exception must be deployed alongside the callable class — include it in every deployment package |
| Org has both legacy Open Interface and new Callable wired to same action | Only one entry point should be active at a time; disable the old interface after confirming the callable works |
| 问题 | 解决方案 |
|---|---|
调用方传递扁平参数但代码期望 | 防御性处理:若 |
| 访问键之前始终做空值检查;若为null则初始化为空映射 |
测试类使用 | 确保每个动作返回相同的信封类型( |
VlocityOpenInterface2迁移破坏了通过引用读取 | 迁移至Callable后,调用方必须读取返回值而非 |
项目中缺少 | 此自定义异常必须与可调用类一起部署 —— 将其包含在每个部署包中 |
| 组织中同时存在旧版Open Interface和新版Callable绑定到同一动作 | 同一时间只能激活一个入口点;确认Callable可用后禁用旧接口 |
Common Anti-Patterns
常见反模式
- contains business logic instead of delegating
call() - Action names are unversioned or not documented
- Input maps assumed to have keys without checks
- Mixed response types (sometimes Map, sometimes String)
- No tests for unsupported actions
- 包含业务逻辑而非委托给其他方法
call() - 动作名称未带版本或未文档化
- 假设输入映射包含指定键而未做检查
- 混合响应类型(有时返回Map,有时返回String)
- 未针对不支持的动作编写测试
Cross-Skill Integration
跨技能集成
| Skill | When to Use | Example |
|---|---|---|
| generating-apex | General Apex work beyond callable implementations | "Create trigger for Account" |
| generating-custom-object / generating-custom-field | Verify object/field availability before coding | "Describe Product2 fields" |
| deploying-metadata | Validate/deploy callable classes | "Deploy to sandbox" |
| 技能 | 使用场景 | 示例 |
|---|---|---|
| generating-apex | 可调用实现之外的通用Apex开发 | "创建Account触发器" |
| generating-custom-object / generating-custom-field | 编码前验证对象/字段的可用性 | "描述Product2字段" |
| deploying-metadata | 验证/部署可调用类 | "部署到沙箱" |
Reference Skill
参考技能
Use the core Apex standards, testing patterns, and guardrails in:
- skills/generating-apex/SKILL.md
使用核心Apex标准、测试模式及约束,请参考:
- skills/generating-apex/SKILL.md
Bundled Examples
捆绑示例
- examples/Test_QuoteByProductCallable/ — read-only query example with
WITH USER_MODE - examples/Test_VlocityOpenInterfaceConversion/ — migration from legacy
VlocityOpenInterface - examples/Test_VlocityOpenInterface2Conversion/ — migration from
VlocityOpenInterface2
- examples/Test_QuoteByProductCallable/ —— 带的只读查询示例
WITH USER_MODE - examples/Test_VlocityOpenInterfaceConversion/ —— 从旧版迁移的示例
VlocityOpenInterface - examples/Test_VlocityOpenInterface2Conversion/ —— 从迁移的示例
VlocityOpenInterface2
Output Expectations
输出预期
Deliverables produced by this skill:
- — Callable class implementing
<ClassName>.clswithSystem.Callabledispatchswitch on action - — Test class with positive, negative, contract, and bulk test methods
<ClassName>Test.cls - — Custom exception class (if not already present in the project)
IndustriesCallableException.cls
本技能生成的交付物:
- —— 实现
<ClassName>.cls的可调用类,含System.Callable分发逻辑switch on action - —— 包含正向、反向、契约及批量测试方法的测试类
<ClassName>Test.cls - —— 自定义异常类(若项目中尚未存在)
IndustriesCallableException.cls
Notes
注意事项
- Prefer deterministic, side-effect-aware callable actions
- Keep action contracts stable; introduce new actions for breaking changes
- Avoid long-running work in synchronous callables; use async when needed
- 优先选择可预测、感知副作用的可调用动作
- 保持动作契约稳定;若需破坏性变更,请新增动作
- 避免在同步可调用类中执行长时间操作;必要时使用异步方式
Reference File Index
参考文件索引
| File | When to read |
|---|---|
| Phase 3 — vanilla |
| Phase 3 — |
| Phase 3 — |
| Phase 4 — test class skeleton (positive, negative, contract, bulk, and null-args cases) |
| Migration — annotated before/after migration pattern (VlocityOpenInterface2 → System.Callable) |
| Phase 3 — complete callable implementation with |
| Phase 4 — full test class covering positive, contract, and unsupported-action cases |
| Phase 3 — custom exception pattern for unsupported actions |
| Reference — reasoning transcript for the Quote-by-Product callable example |
| Phase 3 — migration pattern from legacy |
| Phase 4 — test class for VlocityOpenInterface migration example |
| Phase 3 — custom exception class deployed alongside VlocityOpenInterface conversion |
| Phase 3 — the original legacy VlocityOpenInterface2 class before migration |
| Reference — reasoning transcript for VlocityOpenInterface conversion |
| Phase 3 — migration pattern from |
| Phase 4 — test class for VlocityOpenInterface2 migration example |
| Phase 3 — custom exception class deployed alongside VlocityOpenInterface2 conversion |
| Phase 3 — remote class used by the VlocityOpenInterface2 migration example |
| Reference — reasoning transcript for VlocityOpenInterface2 conversion |
| 文件 | 阅读时机 |
|---|---|
| 阶段3 —— 原生 |
| 阶段3 —— 带 |
| 阶段3 —— 带 |
| 阶段4 —— 测试类骨架(正向、反向、契约、批量及空参数场景) |
| 迁移阶段 —— 带注释的迁移模式示例(VlocityOpenInterface2 → System.Callable) |
| 阶段3 —— 完整的可调用实现,含 |
| 阶段4 —— 覆盖正向、契约及不支持动作场景的完整测试类 |
| 阶段3 —— 针对不支持动作的自定义异常模式 |
| 参考 —— 按产品报价可调用示例的推理记录 |
| 阶段3 —— 从旧版 |
| 阶段4 —— VlocityOpenInterface迁移示例的测试类 |
| 阶段3 —— 与VlocityOpenInterface转换一起部署的自定义异常类 |
| 阶段3 —— 迁移前的旧版VlocityOpenInterface2类 |
| 参考 —— VlocityOpenInterface转换的推理记录 |
| 阶段3 —— 从 |
| 阶段4 —— VlocityOpenInterface2迁移示例的测试类 |
| 阶段3 —— 与VlocityOpenInterface2转换一起部署的自定义异常类 |
| 阶段3 —— VlocityOpenInterface2迁移示例使用的远程类 |
| 参考 —— VlocityOpenInterface2转换的推理记录 |