Skip to content
Back to skills

143 Tier C87e76ba

ASecurity

This guide combines pattern selection (what to use) with implementation best practices (how to use it well). ---

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
businessgosqlexpressrailsapisecuritydocumentation

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 143-tier_c87e76ba --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 143 Tier C87e76ba?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 143 Tier C87e76ba
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-143-tier-c87e76ba/badge)](https://www.skillsdirectory.com/skills/tools-only-143-tier-c87e76ba)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
<!-- TIER: 3 | DETAILED REFERENCE -->
<!-- Read after: SKILL.md, agent-script-reference.md -->
<!-- Contains: Pattern selection + Best practices combined -->

# Patterns & Best Practices

This guide combines pattern selection (what to use) with implementation best practices (how to use it well).

---

## Part 1: Pattern Selection

### Pattern Decision Tree

```
┌─────────────────────────────────────────────────────────────────────────┐
│                     PATTERN DECISION TREE                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  What problem are you solving?                                           │
│  │                                                                       │
│  ├─► "I need to run code BEFORE/AFTER every response"                   │
│  │   └─► Lifecycle Events Pattern                                       │
│  │       File: templates/patterns/lifecycle-events.agent                │
│  │                                                                       │
│  ├─► "After action X, Y must ALWAYS happen"                             │
│  │   └─► Action Callbacks Pattern                                       │
│  │       File: templates/patterns/action-callbacks.agent                │
│  │                                                                       │
│  ├─► "Go to specialist topic, then return with results"                 │
│  │   └─► Bidirectional Routing Pattern                                  │
│  │       File: templates/patterns/bidirectional-routing.agent           │
│  │                                                                       │
│  ├─► "Just starting out - what's the minimum?"                          │
│  │   └─► Hello World                                                    │
│  │       File: templates/agents/hello-world.agent                       │
│  │                                                                       │
│  ├─► "Multiple topics, user chooses where to go"                        │
│  │   └─► Multi-Topic Router                                             │
│  │       File: templates/agents/multi-topic.agent                       │
│  │                                                                       │
│  └─► "Need input validation before actions"                             │
│      └─► Error Handling Pattern                                         │
│          File: templates/components/error-handling.agent                │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
```

---

### Pattern Details

#### 1. Lifecycle Events

**File**: `templates/patterns/lifecycle-events.agent`

**Purpose**: Execute code automatically before and after every reasoning step.

> **⚠️ Deployment Note**: The `run` keyword in lifecycle blocks is **GenAiPlannerBundle only**. AiAuthoringBundle supports `before_reasoning` / `after_reasoning` with `set` statements, but NOT the `run` keyword.

```agentscript
topic conversation:
   before_reasoning:
      set @variables.turn_count = @variables.turn_count + 1
      run @actions.refresh_context                    # ⚠️ GenAiPlannerBundle only
         with user_id=@variables.EndUserId
         set @variables.context = @outputs.fresh_context

   reasoning:
      instructions: ->
         | Turn {!@variables.turn_count}: {!@variables.context}

   after_reasoning:
      run @actions.log_analytics                      # ⚠️ GenAiPlannerBundle only
         with turn=@variables.turn_count
```

| ✅ Good Use Case | ❌ Not Ideal For |
|------------------|------------------|
| Track conversation metrics | One-time setup (use conditional) |
| Refresh context every turn | Heavy processing (adds latency) |
| Log analytics after each response | Actions that might fail often |

---

#### 2. Action Callbacks

**File**: `templates/patterns/action-callbacks.agent`

**Purpose**: Chain deterministic follow-up actions using the `run` keyword.

> **⚠️ Deployment Note**: The `run` keyword is **GenAiPlannerBundle only**. Agents using `run` will NOT be visible in Agentforce Studio.

```agentscript
process_order: @actions.create_order
   with customer_id=@variables.customer_id
   set @variables.order_id = @outputs.order_id
   run @actions.send_confirmation                    # ⚠️ GenAiPlannerBundle only
      with order_id=@variables.order_id
   run @actions.log_activity                         # ⚠️ GenAiPlannerBundle only
      with event="ORDER_CREATED"
```

| ✅ Good Use Case | ❌ Not Ideal For |
|------------------|------------------|
| Audit logging (must happen) | Optional follow-ups (let LLM decide) |
| Send notification after action | Complex branching logic |
| Chain dependent actions | More than 1 level of nesting |

**Critical Rule**: Only 1 level of `run` nesting allowed!

---

#### 3. Bidirectional Routing

**File**: `templates/patterns/bidirectional-routing.agent`

**Purpose**: Navigate to specialist topic, do work, return with results.

```agentscript
# Main hub stores return address
topic main_hub:
   reasoning:
      actions:
         consult_pricing: @utils.transition to @topic.pricing_specialist

# Specialist records where to return
topic pricing_specialist:
   before_reasoning:
      set @variables.return_topic = "main_hub"

   reasoning:
      actions:
         return_with_results: @utils.transition to @topic.main_hub
```

| ✅ Good Use Case | ❌ Not Ideal For |
|------------------|------------------|
| "Consult expert" workflows | Simple linear flows |
| Results need to come back | One-way topic changes |
| Complex multi-step processes | Single-topic agents |

---

#### 4. Multi-Topic Router (Hub-and-Spoke)

**File**: `templates/agents/multi-topic.agent`

**Purpose**: Central topic routes to specialized topics based on user intent.

```agentscript
start_agent topic_selector:
   reasoning:
      instructions: ->
         | Determine what the user needs.
      actions:
         go_orders: @utils.transition to @topic.orders
         go_billing: @utils.transition to @topic.billing
         go_support: @utils.transition to @topic.support
```

| ✅ Good Use Case | ❌ Not Ideal For |
|------------------|------------------|
| Multiple distinct use cases | Single-purpose agents |
| Clear routing criteria | Complex interdependencies |
| Modular topic development | Need to share state heavily |

---

#### 5. Error Handling

**File**: `templates/components/error-handling.agent`

**Purpose**: Validate input before processing, handle failures gracefully.

```agentscript
reasoning:
   instructions: ->
      if @variables.amount is None:
         set @variables.valid = False
         | Please provide an amount.

      if @variables.amount > 10000:
         set @variables.valid = False
         | Amount exceeds maximum allowed.

   actions:
      process: @actions.execute_operation
         available when @variables.valid == True
      retry: @utils.transition to @topic.validation
         available when @variables.operation_failed == True
```

| ✅ Good Use Case | ❌ Not Ideal For |
|------------------|------------------|
| Payment processing | Simple queries |
| Data mutations | Read-only operations |
| Compliance workflows | Low-stakes interactions |

---

### Topic Delegation Pattern (@topic.*)

**Delegation** allows a topic to "consult" another topic and receive control back, unlike permanent transitions.

```agentscript
# ═══════════════════════════════════════════════════════════
# DELEGATION vs TRANSITION
# ═══════════════════════════════════════════════════════════
#
# DELEGATION (@topic.*):     Control CAN return to caller
# TRANSITION (@utils.transition): Control does NOT return
#
# ═══════════════════════════════════════════════════════════

topic main_hub:
   description: "Main conversation hub"
   reasoning:
      actions:
         # DELEGATION - specialist returns control when done
         consult_billing: @topic.billing_specialist
            description: "Ask billing expert for help"
            available when @variables.needs_billing_help == True

         # TRANSITION - permanent move, no return
         go_checkout: @utils.transition to @topic.checkout
            # Note: no description on transitions!

topic billing_specialist:
   description: "Billing expert that returns to caller"
   reasoning:
      instructions: ->
         | Answer billing questions.
         | When done, control returns to main_hub.
```

| Feature | Delegation (`@topic.*`) | Transition (`@utils.transition to`) |
|---------|------------------------|-------------------------------------|
| Returns to caller? | ✅ YES | ❌ NO (permanent) |
| Use in `reasoning.actions` | ✅ YES | ✅ YES |
| Use in `before/after_reasoning` | ❌ NO | ✅ YES (bare syntax) |
| Best for | Consult & return | Menu/workflow navigation |

---

### N-ary Boolean Expressions

AgentScript supports **3 or more conditions** chained with `and`/`or`:

```agentscript
# ═══════════════════════════════════════════════════════════
# THREE+ CONDITIONS WITH AND
# ═══════════════════════════════════════════════════════════

before_reasoning:
   if @variables.is_authenticated and @variables.has_permission and @variables.is_active:
      transition to @topic.authorized

# ═══════════════════════════════════════════════════════════
# THREE+ CONDITIONS WITH OR
# ═══════════════════════════════════════════════════════════

before_reasoning:
   if @variables.is_admin or @variables.is_moderator or @variables.is_owner:
      transition to @topic.elevated_access

# ═══════════════════════════════════════════════════════════
# IN available when CLAUSES
# ═══════════════════════════════════════════════════════════

reasoning:
   actions:
      process_return: @actions.handle_return
         description: "Process customer return request"
         available when @variables.eligible == True and @variables.order_id != None and @variables.tier != "basic"

      premium_action: @actions.premium_feature
         description: "Premium tier feature"
         available when @variables.tier == "premium" or @variables.tier == "enterprise" or @variables.is_trial_premium == True
```

**Key Points:**
- Chain as many conditions as needed with `and` or `or`
- Use `()` grouping for complex expressions: `(a and b) or (c and d)`
- Works in `if` statements and `available when` clauses

---

### Combining Patterns

Patterns can be combined for complex scenarios:

```
┌─────────────────────────────────────────────────────────────┐
│           LIFECYCLE + CALLBACKS + ROUTING                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  topic order_hub:                                            │
│     before_reasoning:                        ◄── Lifecycle   │
│        set @variables.turn_count = ... + 1                   │
│                                                              │
│     reasoning:                                               │
│        actions:                                              │
│           process: @actions.create                           │
│              run @actions.notify           ◄── Callback      │
│              run @actions.log                                │
│                                                              │
│           consult: @utils.transition       ◄── Routing       │
│              to @topic.specialist                            │
│                                                              │
│     after_reasoning:                         ◄── Lifecycle   │
│        run @actions.update_metrics                           │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

---

## Part 2: Best Practices

### 1. Structure & Organization

#### Use Meaningful Names

```agentscript
# ✅ GOOD - Clear, descriptive names
topic order_management:
    description: "Handles order creation, updates, and status inquiries"

# ❌ BAD - Vague names
topic topic1:
    description: "Does stuff"
```

#### Naming Conventions

| Element | Convention | Example |
|---------|------------|---------|
| Agent name | PascalCase with underscores | `Customer_Service_Agent` |
| Topic name | snake_case | `order_management` |
| Variable name | snake_case | `user_email` |
| Action name | snake_case | `get_account_details` |

#### Keep Topics Focused

Each topic should handle ONE category of tasks:

```agentscript
# ✅ GOOD - Single responsibility
topic billing_inquiries:
    description: "Answers questions about invoices, payments, and account balances"

topic order_tracking:
    description: "Provides order status and shipping updates"

# ❌ BAD - Too broad
topic customer_stuff:
    description: "Handles billing, orders, support, and everything else"
```

---

### 2. Variable Management

#### Initialize Variables with Defaults (Recommended)

```agentscript
variables:
    # ✅ RECOMMENDED - Has default value (clearer intent)
    user_name: mutable string = ""
        description: "Customer's full name"

    order_count: mutable number = 0
        description: "Number of orders in cart"

    # ✅ ALSO VALID - Works but less explicit
    # user_name: mutable string
    #     description: "Customer's full name"
```

> **Note**: Variables without defaults ARE supported. However, providing defaults is recommended for clarity.

#### Use Appropriate Types

| Data | Type | Example |
|------|------|---------|
| Names, IDs, text | `string` | `"John Doe"` |
| Counts, amounts | `number` | `42`, `99.99` |
| Flags, toggles | `boolean` | `True`, `False` |

#### Document Every Variable

```agentscript
variables:
    cart_total: mutable number = 0
        description: "Total value of items in cart, in USD"

    needs_approval: mutable boolean = False
        description: "Whether the order requires manager approval (>$10,000)"
```

---

### 3. Topic Design

#### Start with a Topic Selector

```agentscript
start_agent topic_selector:
    description: "Routes users to the appropriate topic based on their needs"
    reasoning:
        instructions: ->
            | Determine what the user needs help with.
            | Ask clarifying questions if the intent is unclear.
        actions:
            orders: @utils.transition to @topic.order_management
                description: "Help with orders and purchases"
            support: @utils.transition to @topic.technical_support
                description: "Technical issues and troubleshooting"
```

#### Provide Clear Descriptions

```agentscript
# ✅ GOOD - Specific and actionable
topic password_reset:
    description: "Helps users reset forgotten passwords and unlock accounts"

# ❌ BAD - Too vague
topic password_reset:
    description: "Password stuff"
```

#### Enable Return Navigation

```agentscript
topic order_details:
    description: "Shows order information"
    reasoning:
        actions:
            back_to_menu: @utils.transition to @topic.topic_selector
                description: "Return to main menu for other requests"
```

---

### 4. Input Binding Patterns

Agent Script supports four input binding patterns:

| Pattern | Syntax | When to Use |
|---------|--------|-------------|
| **LLM Slot-Filling** | `with param=...` | Value from user conversation |
| **Fixed Value** | `with param="constant"` | Always the same |
| **Variable Binding** | `with param=@variables.x` | Using captured data |
| **Mixed** | All combined | Complex actions |

#### Decision Flowchart

```
Is the value always the same?
├─ YES → Use fixed value: with param="constant"
│
└─ NO → Does it come from earlier in conversation?
        ├─ YES → Was it saved to a variable?
        │       ├─ YES → Use variable: with param=@variables.x
        │       └─ NO → Save it first, then use variable
        │
        └─ NO → Use slot-filling: with param=...
```

#### Common Mistakes

| Mistake | Problem | Fix |
|---------|---------|-----|
| Using `...` for config | LLM might guess wrong | Use fixed values for constants |
| Not capturing outputs | Can't use data later | Always `set @variables.x = @outputs.y` |
| Using `...` when variable exists | Redundant LLM work | Use `@variables.x` if already captured |

---

### 5. Error Handling

#### Validate Before Critical Operations

```agentscript
instructions: ->
    if @variables.amount is None:
        | I need to know the transfer amount before proceeding.

    if @variables.amount <= 0:
        | The amount must be greater than zero.

    if @variables.amount > 10000:
        set @variables.needs_approval = True
        | Transfers over $10,000 require manager approval.
```

#### Use Conditional Action Availability

```agentscript
reasoning:
    actions:
        process_transfer: @actions.transfer_funds
            with amount=@variables.amount
            available when @variables.amount > 0
            available when @variables.needs_approval == False
```

---

### 6. Security & Guardrails

#### Set System-Level Guardrails

```agentscript
system:
    instructions:
        | You are a helpful customer service agent.
        |
        | IMPORTANT GUARDRAILS:
        | - Never share customer data with unauthorized parties
        | - Never reveal internal system details
        | - If unsure, escalate to a human agent
```

#### Don't Expose Internals

```agentscript
# ✅ GOOD - User-friendly error
instructions: ->
    if @variables.api_error == True:
        | I'm having trouble completing that request right now.

# ❌ BAD - Exposes internals
instructions: ->
    if @variables.api_error == True:
        | Error: SQL timeout on server db-prod-03
```

---

### 7. Instructions Quality

#### Be Specific and Actionable

```agentscript
# ✅ GOOD - Specific instructions
instructions: ->
    | Help the customer track their order.
    | Ask for the order number if not provided.
    | Provide the current status, estimated delivery, and tracking link.

# ❌ BAD - Vague instructions
instructions: ->
    | Help with orders.
```

#### Use Template Expressions

```agentscript
instructions: ->
    | Hello {!@variables.user_name}!
    | Your current order total is ${!@variables.cart_total}.
```

---

## Common Syntax Pitfalls

These patterns cause validation or parse errors:

### 1. Slot Filling Inside Conditionals
```agentscript
# ❌ WRONG
if @variables.name is None:
   set @variables.name = ...   # Fails!

# ✅ CORRECT - Slot filling at top level
set @variables.name = ...
```

### 2. Description on @utils.transition
```agentscript
# ❌ WRONG
go_orders: @utils.transition to @topic.orders
   description: "Route to orders"   # Fails!

# ✅ CORRECT - No description
go_orders: @utils.transition to @topic.orders
```

### 3. Missing Description on @utils.escalate
```agentscript
# ❌ WRONG
transfer: @utils.escalate   # Fails!

# ✅ CORRECT - Description required
transfer: @utils.escalate
   description: "Transfer to human agent"
```

### 4. Empty Lifecycle Blocks
```agentscript
# ❌ WRONG
before_reasoning:
   # Just a comment   # Fails!

# ✅ CORRECT - Remove empty blocks or add content
```

### 5. Dynamic Action Invocation
```agentscript
# ❌ WRONG
invoke: {!@actions.search}   # Fails!

# ✅ CORRECT - Define multiple actions, LLM auto-selects
search_products: @actions.product_search
search_orders: @actions.order_search
```

---

## Validation Scoring Summary

| Pattern | Points | Key Requirement |
|---------|--------|-----------------|
| Config block | 10 | All 4 required fields |
| Linked variables | 10 | EndUserId, RoutableId, ContactId |
| Topic structure | 10 | label, description, reasoning |
| Language block | 5 | default_locale present |
| Lifecycle blocks | 5 | Proper before/after structure |
| Action callbacks | 5 | No nested run |
| Error handling | 5 | Validation patterns |
| Template expressions | 5 | {!@variables.x} syntax |

---

## Quick Reference Checklist

Before deploying an agent, verify:

- [ ] All topics have clear descriptions
- [ ] All variables have descriptions and defaults
- [ ] All actions have input/output descriptions
- [ ] System guardrails are defined
- [ ] Error handling is in place for critical operations
- [ ] Navigation back to main menu from all topics
- [ ] Template expressions use correct syntax `{!@variables.name}`
- [ ] Consistent indentation (tabs recommended)

---

## Slot Filling Reliability Patterns

### Problem: LLM Fails to Extract Values Correctly

Slot filling (`with param=...`) relies on LLM inference, which can fail in subtle ways:

| Symptom | What Happened | Example |
|---------|---------------|---------|
| Empty JSON `{}` sent to action | LLM couldn't find value in conversation | User said "look up my account" without ID |
| Wrong field names | LLM abbreviated or guessed | `_id` instead of `account_id` |
| Wrong value extracted | LLM picked similar value from context | Picked Contact ID instead of Account ID |
| Retry/crash cycles | No recovery path after failure | Agent keeps trying same extraction |

### Root Cause

The `...` syntax is **probabilistic** - the LLM infers what value to use. For critical inputs (IDs, amounts, required fields), this unreliability causes downstream failures.

### Solution: Deterministic Critical Input Collection

Instead of relying on slot filling for critical inputs, use this 5-pattern approach:

#### Pattern 1: First-Interaction Collection

Tell the LLM its PRIMARY GOAL is to collect the input:

```agentscript
reasoning:
   instructions: ->
      | YOUR PRIMARY GOAL: Collect the account ID from the user.
      | Do NOT proceed with any other actions until account_id is captured.
      |
      if @variables.account_id == "":
         | ⚠️ Account ID not yet collected. ASK the user for it.
```

**Why it works:** Explicit priority instructions override LLM's tendency to "help" by guessing.

#### Pattern 2: Variable Setter Action

Create a **dedicated action** to capture and validate critical input:

```agentscript
actions:
   capture_account_id:
      description: "Captures and validates the Salesforce Account ID from user"
      inputs:
         account_id: string
            description: "The 18-character Salesforce Account ID (starts with 001)"
            is_required: True
      outputs:
         validated_id: string
            description: "The validated account ID (empty if invalid)"
         is_valid: boolean
            description: "Whether the ID is valid"
      target: "flow://Validate_Account_Id"
```

**Why it works:** The Flow performs server-side validation, ensuring only valid IDs are stored.

#### Pattern 3: Single-Use Pattern

Make the setter action **unavailable once the variable is set**:

```agentscript
reasoning:
   actions:
      validate_id: @actions.capture_account_id
         with account_id=...
         set @variables.account_id = @outputs.validated_id
         set @variables.account_id_validated = @outputs.is_valid
         # ★ SINGLE-USE: Becomes unavailable after successful capture
         available when @variables.account_id == ""
```

**Why it works:** Prevents redundant re-collection attempts that can introduce errors.

#### Pattern 4: Null Guard All Downstream Actions

Block ALL other actions until critical input is validated:

```agentscript
reasoning:
   actions:
      # ★ RESEARCH ACTION - Uses variable, NOT slot filling
      do_research: @actions.research_account
         with account_id=@variables.account_id    # Variable binding!
         available when @variables.account_id_validated == True

      # ★ TOPIC TRANSITION - Also guarded
      go_research: @utils.transition to @topic.research
         available when @variables.account_id_validated == True
```

**Why it works:** Ensures downstream actions receive valid data, not LLM guesses.

#### Pattern 5: Explicit Action References in Instructions

Guide the LLM on WHICH action to use:

```agentscript
instructions: ->
   | To capture the account ID, use {!@actions.capture_account_id}.
   | This ensures the ID is validated before proceeding.
```

**Why it works:** Reduces ambiguity about which action handles input collection.

---

### When NOT to Use Slot Filling

| Use Slot Filling (`...`) | Use Variable/Fixed Value |
|--------------------------|--------------------------|
| Optional, non-critical inputs | Critical IDs (account, order, case) |
| User preference inputs | Values that must be validated |
| One-time collection | Values used across multiple actions |
| Simple text descriptions | Values with specific formats (dates, IDs) |

**Decision Rule:** If invalid input would cause downstream failure, use deterministic collection.

---

### Troubleshooting Slot Filling Issues

#### Symptom: Empty JSON Sent to Action

```
ERROR: Action received {} instead of {account_id: "001..."}
```

**Cause:** LLM couldn't extract value from conversation.

**Fix:**
1. Add explicit collection instructions: "YOUR PRIMARY GOAL: collect account_id"
2. Use a dedicated setter action with clear input description
3. Add `available when @var != ""` guard on downstream actions

#### Symptom: Wrong Field Names

```
ERROR: Property _id not found. Expected: account_id
```

**Cause:** LLM inferred/abbreviated field name.

**Fix:**
1. Use exact field name in action input description
2. Add instruction: "The account_id must be the exact value provided by user"
3. Use validation action that normalizes input

#### Symptom: Agent Retries Then Crashes

```
Agent attempted 5 times, then failed with: Internal Error
```

**Cause:** No recovery path after extraction failure.

**Fix:**
1. Add retry counter: `collection_attempts: mutable number = 0`
2. Increment on each attempt: `set @var = @var + 1`
3. Add escape condition: `if @variables.attempts > 3: | Please verify your ID format`

---

### Complete Pattern Template

See `templates/patterns/critical-input-collection.agent` for a complete implementation demonstrating all five patterns together.

---

## Related Documentation

- [Agent Script Reference](agent-script-reference.md) - Complete syntax guide
- [Actions Reference](actions-reference.md) - Action integration details
- [Prompt Templates](prompt-templates.md) - Prompt Template integration

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.