Skip to content
Everything Agents

Lesson 1 of 14 · 6 min

The scenario

Read this first. Every snippet, diagram, and bug in the tutorial comes from this one refund agent.

Every concept, code snippet, bug, and fix in this tutorial comes from one concrete project: a customer-service refund agent for a fictional company, Acme Corp. Read this section first.

What the agent is supposed to do

A customer messages support, the agent walks them through a refund. The end-to-end flow:

  1. Customer asks for a refund.
  2. Agent collects the customer's email and verifies them.
  3. Agent looks up the order.
  4. Agent confirms refund details with the customer.
  5. Agent issues the refund and sends a confirmation.

It also handles edge cases: escalation to a human, off-topic questions, and ambiguous intent.

The five-topic graph

The agent is a small finite state machine. Each box is a subagent in the .agent file.

Topic graph for the refund agent. The router decides where each turn goes; subagents handle the work.

The router decides where each turn goes. Subagents decide what to do once they own the turn.

The four backing Apex actions

Apex classInputsOutputsPurpose
VerifyCustomeremailcustomer_id, verifiedVerify a customer by email
FindOrderorder_idorder_status, order_amount, refundable_untilLook up an invoice
IssueReturnorder_idrefund_confirmationIssue the refund and return a code
SendReplyreply_textdelivery_statusSend the customer a final message

These are real @InvocableMethod Apex classes deployed to the org.

A cutaway view of the refund agentThe customer talks to the planner. The planner sits inside the Salesforce org and can call four Apex actions: VerifyCustomer, FindOrder, IssueReturn, SendReply. The dashed line is the org boundary; everything inside it runs as the agent's running user.customerSALESFORCE ORG · runs as the agent userPLANNER5 topics12 variablesenabled-tools gateafter_reasoningVerifyCustomerverify by emailapex://FindOrderlook up orderapex://IssueReturnprocess refundapex://SendReplysend confirmationapex://the planner picks topics and tools; the Apex actions decide what is true

The variables we track across turns

customer_email        : ""              # the email the customer typed
customer_verified     : False           # the gate everything depends on
verified_flag         : ""              # raw "true"/"false" string from VerifyCustomer
customer_id           : ""              # e.g. "cust_100", only set if verified
order_id              : ""              # e.g. "INV-1007"
order_loaded          : False           # was FindOrder called yet?
order_status          : ""              # "paid", "refunded", "pending"
order_amount          : ""              # "$129.00"
refundable_until      : ""              # "2026-06-01"
refund_issued         : False
refund_confirmation   : ""              # "RFND-INV-1007-766349"
reply_sent            : False

These are the symbolic state. They make deterministic gating possible.

A representative happy-path conversation

A successful refund: every action call is real Apex.

Every action call above is a real Apex invocation. Every variable update along the way is visible in the session trace. This is what we are building.

A taste of the source

The .agent file's identity-verification topic, condensed:

subagent identity_verification:
    actions:
        verify_customer:
            target: "apex://VerifyCustomer"
            inputs:  { email: string }
            outputs:
                customer_id: string
                    description: "cust_NNN format. Empty means NOT verified."
                verified: string
                    description: "Literal 'true' or 'false' from Apex."

    reasoning:
        instructions: ->
            if @variables.customer_verified == False:
                | Goal: call verify with the customer's email. Ask for one if
                | you don't have it yet.
        actions:
            verify: @actions.verify_customer
                with email = ...
                set @variables.customer_id    = @outputs.customer_id
                set @variables.verified_flag  = @outputs.verified
            go_refund: @utils.transition to @subagent.refund_processing
                available when @variables.customer_verified == True

    after_reasoning:
        if @variables.verified_flag == "true":
            set @variables.customer_verified = True

That is the full vocabulary. Topic graph, variables, Invocable Apex, gates, traces, and one running example. We will refer back to these snippets throughout.

Quick check

Which of these is the gate everything else depends on?