SfSkills Domains Docs GitHub

Home / agentforce / agent-action-error-handling

agent-action-error-handling

Design Invocable Apex actions that return deterministic, agent-friendly errors instead of surfacing raw exceptions to the LLM. NOT for authoring the action itself — @InvocableMethod schema, labels, security context — use agentforce/custom-agent-actions-apex. NOT for the Apex tests that force each error branch — use agentforce/agent-action-unit-tests.

Open the skill folder on GitHub


Agent Action Error Handling

Agentforce agents receive the return value of an Invocable action as-is and feed it back into the LLM loop. An unhandled exception becomes a Flow or framework error — the agent cannot reason about it, often re-invokes the action with the same inputs, and occasionally confabulates success. This skill defines a Response type that always returns (status, reason_code, user_message) so the subagent instructions can route deterministically.

Terminology. Salesforce renamed agent topics to subagents in April 2026. Nothing about behaviour changed, and the API surface kept the old word — GenAiPlugin is still the metadata type behind a subagent, and GenAiFunction is still the action. This skill says subagent instructions for what older docs and your org's metadata call topic instructions.

The Platform Rule Everything Follows From

An @InvocableMethod must return one result per input, in the same order, even when errors occur — the inputs and outputs "must match on both the size and the order" (InvocableMethod Annotation).

So an error is not an exception you throw. It is a value you return in the slot belonging to the failing request. A thrown exception breaks the contract for the whole batch, not just the request that failed.

Two further platform rules shape the class: the method must be static, public or global, and live in an outer class; and there is one invocable method per class. One action is one verb — see templates/agentforce/AgentActionSkeleton.cls.

The Envelope

FieldTypePurpose
statusOK | USER_ERROR | SYSTEM_ERRORLocus of control — whose problem is this
reasonCodestable enum stringWhat the subagent instructions branch on
userMessage≤140 chars, authoredSafe to read aloud verbatim
retryableBooleanWould the same inputs plausibly succeed

status and retryable are independent axes. A row lock is a retryable system error; a validation failure is a terminal user error; a 503 is a retryable system error. Collapsing them into one Boolean success is the single most common cause of agent retry loops.

  1. Design the Response class with the four fields above. Register every

    reasonCode in Agent_Reason_Code__mdt so Apex, subagent instructions, and dashboards share one contract.

  2. Structure the method in two phases — validate and collect, then one bulkified

    Database.<dml>(records, false, AccessLevel.USER_MODE) — and assign results back by index into a pre-sized output list. Per-row DML raises an uncatchable LimitException under bulk invocation, which defeats every catch you write.

  3. Classify by locus of control, branching on Database.Error.getStatusCode()

    or the HTTP status code — never on message text, which is localised and reworded between releases. Log the raw exception to templates/apex/ApplicationLogger.cls; never put getMessage() in userMessage.

  4. Write one test per reason code asserting the code, the retryable flag, and

    that no raw platform error text reached userMessage. Coverage percentage is not the signal; assertions-per-reason-code is.

  5. Add one subagent instruction per outcome class, including an explicit *"do not

    call the action again"* for terminal codes — the planner's default on an unsatisfied goal is to retry.

  6. Run the Testing Center / sf agent test run scenarios that exercise each

    branch and confirm the agent's wording matches the instruction for each code.

Key Considerations

Worked Examples (see references/examples.md)

Common Gotchas (see references/gotchas.md)

Top LLM Anti-Patterns (full list in references/llm-anti-patterns.md)

Official Sources Used

Package files