| `reasoning` (LLM turn) | 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 |
The `before_reasoning:` and `after_reasoning:` lifecycle hooks are validated. Content goes **directly** under the block (no `instructions:` wrapper). See "Lifecycle Hooks" section below for correct syntax.
### Cost Optimization Pattern
Fetch data once in `before_reasoning:`, cache in variables, reuse across topics.
## Lifecycle Hooks
```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 = True
```
**Key Points:**
- Content goes **directly** under `before_reasoning:` / `after_reasoning:` (NO `instructions:` wrapper)
- Reliable primitives: `set`, `if`/`else`, `transition to`. `run` has inconsistent runtime behavior across bundle types — use it in `reasoning.actions:` or `instructions: ->` instead
-`before_reasoning:` is FREE (no credit cost) - use for data prep
-`after_reasoning:` is FREE (no credit cost) - use for logging, cleanup
-`transition to` works in `after_reasoning:` — but if a topic transitions mid-reasoning, the original topic's `after_reasoning:` does NOT run
**❌ 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
```
## Supervision vs Handoff
| Term | Syntax | Behavior | Use When |
|------|--------|----------|----------|
| **Handoff** | `@utils.transition to @topic.X` | Control transfers completely, child generates final response | Checkout, escalation, terminal states |
`@inputs` is only available in `with` directives during action invocation. Using `@inputs` in a post-action `set` causes **silent runtime failure** — the action executes but the `set` silently drops, leaving the variable unchanged. No trace error; the FunctionStep shows no output capture.
```agentscript
# WRONG — silent failure, @inputs out of scope after action executes
run @actions.get_station_status
with station_name = ...
set @variables.station = @inputs.station_name # FAILS SILENTLY
# RIGHT — use @outputs (if action echoes the value) or capture input before the call
set @variables.station = @variables.selected_station # capture before
run @actions.get_station_status
with station_name = @variables.station
set @variables.status = @outputs.status # @outputs is valid here
```
**Diagnosis:** A FunctionStep that completes with no output capture (set directives dropped) indicates an `@inputs` scope violation. The action succeeds — only the assignment fails.
Similarly, `@outputs` is only available in `set` and `if` directives immediately following the action invocation — not in instructions, pipe lines, or later actions.
Certain common words cannot be used as `@InvocableVariable` names in Apex classes called by Agent Script. Using them causes "SyntaxError: Unexpected '{keyword}'" during agent script compilation. (Validated March 2026)
**Reserved names (cannot use as `@InvocableVariable`):**