afv-library/plugins/builder/salesforce-development/skills/agentforce-generate/references/zen-of-agentscript.md

8.9 KiB
Raw Blame History

The Zen of AgentScript

These are enforceable, unordered authoring rules shipped with the skill. Each rule includes a test that can fail. No rule takes precedence over another; a valid design satisfies all applicable rules at the same time.

Give each reachable branch one next outcome

For every branch, choose exactly one primary outcome:

answer | ask | invoke an action | transition | refuse | escalate

The model may explain an outcome, but it must not receive two incompatible duties.

Pass:

  • A router transitions without answering the underlying request.
  • A request handler answers or invokes its domain action.
  • A verification gate asks for missing proof or transitions after proof.

Fail:

  • Global instructions say “always answer,” while a router branch says “do not answer; transition.”
  • A branch both escalates permanently and promises to continue the task.

Declare no mutable variable without a named consumer

Before adding a variable, identify at least one concrete consumer:

if | available when | transition | action input | later-turn exact output

The variable must also represent one of:

  • trusted action output;
  • authorization, eligibility, or confirmation proof;
  • an exact value required by later deterministic logic; or
  • a value explicitly required beyond the conversation-history window.

Otherwise, leave the information in conversation history.

Pass:

authenticated: mutable boolean = False

lookup_profile: @actions.get_profile
    available when @variables.authenticated == True

Fail:

has_greeted: mutable boolean = False
question_asked: mutable boolean = False
conversation_stage: mutable string = "collecting"

Add deterministic control only for a named cause

Every if, available when, automatic run, or forced transition must cite one cause in the design:

regulation | authorization | irreversible consequence |
external ordering | observed trace failure

If the decision depends on unstructured current intent and none of those causes applies, leave the decision to model reasoning.

Pass:

  • Hide a refund action until the exact amount and explicit confirmation are recorded.
  • Prevent step 2 until step 1s external action returns success=True.

Fail:

  • Add a current_step counter because a conversation happens to have several questions.
  • Force every follow-up back into an old subagent without a reproduced routing defect.

Create a subagent only when the boundary changes behavior

A subagent boundary must change at least one of:

objective | instructions | available actions | authority | escalation behavior

The difference must also be large enough that the two behaviors cannot remain coherent in one scope. A greeting, cancellation acknowledgment, completion message, ambiguity question, or ordinary dialogue step is a branch by default, not a separate subagent.

For a focused single-domain agent, the concrete default is:

start_agent event_search:
    reasoning:
        actions:
            search: @actions.search_events

That means one execution block and zero subagent blocks—not an agent_router that only transitions to event_search.

Pass:

  • Separate public FAQ actions from authenticated account actions.
  • Separate permanent human escalation from a returning specialist consultation.

Fail:

  • Create greeting, collect_name, collect_email, and present_results subagents solely to represent dialogue stages.
  • Wrap one read-only event search in a router and a cancellation subagent when the single search scope can cancel without invoking its action.

Make model-visible instructions concrete and self-contained

Write what the model must do now. Do not tell it to inspect AgentScript constructs such as the active subagent, @variables, lifecycle hooks, or “the reasoning instructions.”

For every branch, concatenate the effective system text and resolved reasoning text. The result must still prescribe one compatible outcome from the branch-outcome rule.

Pass:

Ask for the minimum information needed to verify identity. Do not use
account-changing actions.

Fail:

Inspect the current subagent and variables, then follow the response duty in
the reasoning instructions.

Use slot filling unless the value is controlled

Bind an action input with ... when the model can safely extract it from the current turn and surviving history.

Use @variables.x only when the value is trusted, canonicalized, needed by deterministic logic, or must be reused after its action-output scope ends. Use a literal only for an actual constant.

Action descriptions need:

  1. the actions outcome;
  2. when to choose it over its closest alternative; and
  3. any material consequence.

They do not need to script the surrounding conversation.

Pass:

find_events: @actions.search_events
    with interest=...

Fail:

  • End one turn with setVariables just to copy “jazz” from history, then call the search action on the next turn.
  • Pin a user-correctable value from stale state when ... would use the latest turn.

Bind consequential actions to machine-checkable preconditions

For an action that changes money, access, records, commitments, or external state:

  1. bind the exact target and material parameters;
  2. make required authorization and confirmation machine-checkable;
  3. keep the action unavailable until those checks pass;
  4. record the action result or idempotency key when repeat execution would cause harm; and
  5. do not advance workflow state when the action fails.

Pass:

issue_refund: @actions.refund
    with order_id=@variables.verified_order_id
    with amount=@variables.confirmed_amount
    available when @variables.customer_verified == True
    available when @variables.refund_confirmed == True
    available when @variables.refund_id == ""
    set @variables.refund_id = @outputs.refund_id

Fail:

  • A prose instruction says “only refund after confirmation,” but the action is always available.
  • current_step advances after @outputs.success == False.

Treat action execution—not model text—as evidence

The agent may claim an external fact or completed action only when the trace contains the corresponding successful action result.

Use direct @outputs chaining inside the same action scope. Persist only the fields a later deterministic consumer needs. If later logic needs only complete-versus-incomplete, persist a trusted boolean outcome rather than a display-only external identifier. Persist the identifier itself only when an exact-ID consumer exists, such as a later action input, idempotency guard, or required later-turn evidence check.

Pass:

  • The response names the returned status from the order lookup.
  • A later action receives the canonical ID returned by verification.
  • A final verification writes verified=True for repeat gating while its display-only receipt remains in the action result and conversation history.

Fail:

  • The model says “your refund was issued” because the action was visible or it intended to call it.
  • An empty or failed action result is presented as success.
  • A final receipt ID is copied into mutable state even though later logic tests only whether completion occurred.

Give every flag, cache, and latch a complete lifecycle

For each persistent control value, document:

owner | writer | reader | reset | expiry | correction behavior | cancel path

Reject the value if any field is missing.

Additional hard rules:

  • Keep one source of truth; do not store both current_step and equivalent completion flags.
  • A cache must define when external data is refreshed.
  • A focus latch must be justified by a reproduced trace and allow the next user turn to cancel or change intent.

Fail:

  • open_gate bypasses fresh routing and the locked subagent has no exit action.
  • data_loaded=True suppresses refresh for the rest of the conversation.

Merge only on conversation behavior, with syntax as a hard precondition

Every candidate must first pass:

parse | lint | reference resolution | compile | emitted-artifact inspection

Then compare parent and candidate on multi-turn scenarios:

  • natural follow-up;
  • correction of an earlier value;
  • intent change during a workflow;
  • cancellation during verification or confirmation;
  • action success, empty result, and failure;
  • trusted authorization;
  • consequential confirmation;
  • exact later-turn action data flow; and
  • completion without repeated actions.

Merge only when:

  1. the candidate has no new deterministic validation failure;
  2. safety, authorization, confirmation, and release boundaries do not regress;
  3. protected parent behaviors remain correct; and
  4. the candidate improves or ties conversation outcomes without adding unjustified state, turns, or tool calls.

Parser success alone is not evidence that the agent behaves well.