Salesforce AI December 3, 2025 18 min read

Strategy Stitching: How Composable Reasoning Changes AI Development

A strategy is not a prompt. It is a meta-reasoning directive that changes how the AI thinks. sf-fabric has 13 of them. Combined with 127 patterns, that is 1,651 unique AI behaviors from a composable system.

Tyler Colby · Founder, Colby's Data Movers

What Is a Strategy?

A strategy is a JSON file with two fields: a description and a prompt. The prompt gets prepended to the system message before the pattern content. It does not tell the AI what to do. It tells the AI how to think while doing it.

// From sf-fabric-core/src/strategy.rs

pub struct Strategy {
    pub description: String,
    pub prompt: String,
}

pub struct StrategyStore {
    strategies: HashMap<String, Strategy>,
}

impl StrategyStore {
    pub fn load_dir(&mut self, dir: &Path) -> Result<usize> {
        let mut count = 0;
        for entry in std::fs::read_dir(dir)? {
            let path = entry?.path();
            if path.extension() == Some("json".as_ref()) {
                let name = path.file_stem()
                    .and_then(|n| n.to_str())
                    .unwrap_or("").to_string();
                let content = std::fs::read_to_string(&path)?;
                let strategy: Strategy =
                    serde_json::from_str(&content)?;
                self.strategies.insert(name, strategy);
                count += 1;
            }
        }
        Ok(count)
    }
}

Here is what a strategy JSON file looks like:

// strategies/cot.json (Chain-of-Thought)
{
  "description": "Chain-of-Thought: Break down complex problems into explicit reasoning steps",
  "prompt": "Think through this problem step by step. Before generating any output, explicitly state:\n1. What you understand about the requirements\n2. What constraints apply\n3. What approach you will take and why\n4. What edge cases need consideration\n\nOnly after completing this analysis should you generate the actual output. Show your reasoning."
}

// strategies/governor_aware.json
{
  "description": "Governor-Aware: Optimize for Salesforce governor limits",
  "prompt": "You are operating in a Salesforce execution context with strict governor limits. For every piece of code you generate or review:\n- Count SOQL queries (limit: 100 synchronous, 200 async)\n- Count DML statements (limit: 150)\n- Track heap size implications (limit: 6MB sync, 12MB async)\n- Check CPU time impact (limit: 10s sync, 60s async)\n- Verify no SOQL or DML inside loops\n- Ensure collections are used for bulk operations\n- Consider Limits class for runtime monitoring\n\nExplicitly note the governor limit impact of your recommendations."
}

// strategies/security_first.json
{
  "description": "Security-First: Prioritize security in all recommendations",
  "prompt": "Apply security-first thinking to everything you generate or review:\n- Check CRUD permissions before every DML operation (Schema.SObjectType.*.isCreateable(), etc.)\n- Check FLS before every field access (Schema.SObjectField.*.isAccessible())\n- Never use WITH SECURITY_ENFORCED in dynamic SOQL without fallback\n- Validate all external input (no SOQL injection, no XSS in Visualforce/LWC)\n- Use the principle of least privilege for permission sets\n- Flag any hardcoded credentials, IDs, or org-specific values\n- Consider sharing rules and record access implications\n\nSecurity issues are always Critical severity. Never downgrade them."
}

The 13 Strategies

Strategy inventory:

General reasoning:
  cot              Chain-of-Thought (step-by-step reasoning)
  tot              Tree-of-Thought (explore multiple paths)
  reflexion        Self-critique and revision
  self_consistent  Generate multiple answers, pick consensus

Salesforce-specific:
  governor_aware   Optimize for governor limits
  security_first   CRUD/FLS/sharing as primary concern
  bulkification    Bulk data operation patterns
  isv_compliant    ISV/AppExchange packaging rules
  migration_safe   Safe data migration practices
  multi_org        Multi-org architecture awareness
  agentforce_architect  Agentforce agent design patterns

Meta-strategies:
  minimal          Concise, minimal output
  verbose          Detailed explanations with examples

The Salesforce-specific strategies are what make sf-fabric different from general-purpose AI tools. Governor-aware reasoning is not something you can bolt onto ChatGPT. It requires deep knowledge of Salesforce's execution context, governor limits, and the specific patterns that avoid them. That knowledge is encoded once in the strategy prompt and applied to every pattern that uses it.

The Stitching Order

When a request comes in, the Chatter assembles the system message from three components in a specific order: strategy first, then context, then pattern.

// From sf-fabric-core/src/chatter.rs

pub async fn build_session(
    &self, request: &ChatRequest
) -> Result<Session> {
    let mut session = /* ... */;
    let mut system_parts: Vec<String> = Vec::new();

    // 1. Strategy prompt (prepended FIRST)
    if let Some(ref strategy_name) = request.strategy_name {
        let strategy = self.strategies.get(strategy_name)?;
        system_parts.push(strategy.prompt.clone());
    }

    // 2. Context content (optional background)
    if let Some(ref context_name) = request.context_name {
        let context = self.contexts.get(context_name)?;
        system_parts.push(context.to_string());
    }

    // 3. Pattern system prompt (with variable substitution)
    if let Some(ref pattern_name) = request.pattern_name {
        let pattern = self.patterns.get(pattern_name)?;
        let rendered = self.template_engine.render(
            &pattern.system_prompt,
            &request.message,
            &request.variables,
        )?;
        system_parts.push(rendered);
    }

    // Combine: strategy + context + pattern
    if !system_parts.is_empty() {
        let mut system_content =
            system_parts.join("\n\n");

        // Resolve {{sf:...}} variables if org targeted
        if let Some(ref org_alias) = request.org_alias {
            system_content =
                sf_fabric_salesforce::resolve_sf_variables(
                    &system_content, org_alias
                ).await?;
        }

        session.add_message(Message::system(system_content));
    }

    // Add user message
    if !request.message.is_empty() {
        session.add_message(Message::user(&request.message));
    }

    Ok(session)
}

The stitching order matters. Strategy goes first because it sets the meta-reasoning frame. When the AI encounters the pattern instructions, it is already "thinking" in the strategy's mode. A governor_aware strategy followed by a create_trigger pattern produces code that is governor-limit-safe from the first line. The strategy is not an afterthought that checks the code later. It shapes the generation process itself.

Same Pattern, Different Strategies

The power of composability becomes obvious when you see the same pattern produce different output with different strategies. Here is review_apex applied to this code:

// Input code to review
public class AccountProcessor {
    public static void processAccounts(List<Id> accountIds) {
        for (Id accId : accountIds) {
            Account acc = [SELECT Id, Name, Industry
                FROM Account WHERE Id = :accId];
            acc.Description = 'Processed on ' +
                Date.today().format();
            update acc;
        }
    }
}

review_apex + governor_aware:

CRITICAL: SOQL query inside for loop (Line 4)
  Governor impact: Will consume 1 SOQL query per account.
  With 200 accounts, this exhausts the 100-query sync limit.
  Fix: Query all accounts before the loop.

CRITICAL: DML inside for loop (Line 7)
  Governor impact: Will consume 1 DML statement per account.
  With 150+ accounts, this hits the 150-DML limit.
  Fix: Collect updates and perform single DML after loop.

Refactored:
  public static void processAccounts(List<Id> accountIds) {
      List<Account> accounts = [SELECT Id, Name, Industry
          FROM Account WHERE Id IN :accountIds];
      for (Account acc : accounts) {
          acc.Description = 'Processed on ' +
              Date.today().format();
      }
      update accounts;
  }
  // SOQL queries used: 1 (was N)
  // DML statements used: 1 (was N)

review_apex + security_first:

CRITICAL: No CRUD check before DML (Line 7)
  The update executes without verifying the running user
  has update permission on Account.
  Fix: Add Schema.SObjectType.Account.isUpdateable() check.

CRITICAL: No FLS check on Description field (Line 6)
  Writing to Account.Description without verifying
  field-level access.
  Fix: Check Schema.SObjectField.Description.isUpdateable().

WARNING: SOQL without WITH SECURITY_ENFORCED
  The query on Line 4 does not enforce sharing rules.
  This may return records the running user should not see.

Refactored:
  public static void processAccounts(List<Id> accountIds) {
      if (!Schema.SObjectType.Account.isUpdateable()) {
          throw new SecurityException(
              'Insufficient privileges to update Account');
      }
      if (!Schema.SObjectType.Account.fields
          .Description.getDescribe().isUpdateable()) {
          throw new SecurityException(
              'No write access to Account.Description');
      }
      List<Account> accounts = [SELECT Id, Description
          FROM Account
          WHERE Id IN :accountIds
          WITH SECURITY_ENFORCED];
      // ... rest of processing
  }

Same input code. Same review_apex pattern. Completely different reviews. The governor_aware strategy caught the bulkification issues and showed the governor limit math. The security_first strategy caught the CRUD/FLS violations and showed the security checks. Both reviews are correct. Both are critical. Neither is complete without the other.

This is why composability is better than a monolithic "review everything" pattern. A monolithic pattern would try to cover both governor limits and security in one pass, diluting the focus on each. With strategy stitching, you run the review twice with two strategies and get deeper coverage on both axes.

Why Composable Beats Monolithic

The monolithic approach is tempting: build one giant prompt that covers everything. We tried it. Here is why it fails:

  1. Token budget. A pattern that covers governor limits, security, naming, performance, testing, and architecture is 6,000+ tokens of system prompt. That leaves less room for the actual code being reviewed. Focused strategies keep each system prompt under 3,000 tokens total.
  2. Attention dilution. LLMs have finite attention. A prompt with 8 priorities produces shallow coverage of all 8. A prompt with 2 priorities produces deep coverage of those 2. Run it 4 times with 4 strategies and you get deep coverage of all 8, each in its own focused pass.
  3. Maintenance burden. Updating the security section of a monolithic prompt risks breaking the governor limits section. With composable strategies, each JSON file is independent. Update governor_aware.json without touching security_first.json.
  4. Combinatorial coverage. 127 monolithic patterns give you 127 behaviors. 127 patterns with 13 strategies give you 1,651 behaviors. The composable system covers more ground with less code.

Strategy Recommendations

Each pattern's metadata includes recommended_strategies. These are not enforced, but they represent the strategies that produce the best results for that pattern:

Pattern               | Recommended Strategies
--------------------------------------------------
review_apex           | cot, governor_aware
review_security       | security_first, reflexion
create_trigger        | governor_aware, bulkification
create_test_class     | cot, self_consistent
analyze_org_health    | tot, governor_aware
migrate_data          | migration_safe, bulkification
package_for_exchange  | isv_compliant, security_first
design_multi_org      | multi_org, cot
create_agent_action   | agentforce_architect, cot

The recommendations come from testing. We ran each pattern with all 13 strategies and evaluated the output quality. governor_aware consistently improves code generation patterns. security_first consistently improves review patterns. reflexion (which asks the AI to critique its own output before finalizing) consistently improves complex architectural patterns.

The user can ignore recommendations. Sometimes you want a security-first code review of a migration script, even though the pattern recommends migration_safe. The recommendation is a default, not a constraint.

The Assembly Pipeline

Here is the complete pipeline from user command to LLM request:

User command:
  sf-fabric --pattern review_apex \
            --strategy governor_aware \
            --org prod \
            --message "$(cat MyClass.cls)"

Assembly pipeline:
  1. Load strategy: governor_aware.json
     -> "You are operating in a Salesforce execution
         context with strict governor limits..."
     -> 200 tokens

  2. Load pattern: review_apex/system.md
     -> "# IDENTITY\nYou are a senior Salesforce
         developer..."
     -> 800 tokens

  3. Resolve {{sf:*}} variables against prod org
     (if any exist in the pattern)

  4. Substitute {{input}} with MyClass.cls contents

  5. Build system message:
     [governor_aware prompt]
     \n\n
     [review_apex prompt with resolved variables]

  6. Build message list:
     System: [assembled system content]
     User: [MyClass.cls contents]

  7. Send to vendor (Anthropic/OpenAI/Ollama)
     via VendorManager.resolve()

  8. Receive response, add to session, persist if named

Total assembly time: under 5ms. The LLM call dominates at 3-15 seconds. The assembly is overhead-free in practice.

Building Custom Strategies

Adding a custom strategy is creating one JSON file:

// strategies/hipaa_compliance.json
{
  "description": "HIPAA Compliance: Healthcare data handling",
  "prompt": "You are generating or reviewing code that handles Protected Health Information (PHI). Apply HIPAA compliance requirements:\n- All PHI fields must be encrypted at rest (Platform Encryption)\n- Access to PHI must be logged (Field History Tracking)\n- PHI must never appear in debug logs or error messages\n- SOQL queries returning PHI must use WITH SECURITY_ENFORCED\n- API responses containing PHI must be marked as sensitive\n- Bulk data operations with PHI require audit trail\n- PHI must not be stored in non-encrypted custom settings\n\nFlag any PHI handling that violates these requirements as CRITICAL."
}

Drop it in the strategies directory. It is immediately available. You can now run any pattern with HIPAA compliance reasoning:

sf-fabric --pattern review_apex \
          --strategy hipaa_compliance \
          --message "$(cat PatientController.cls)"

The review_apex pattern now reviews the code through a HIPAA lens. It will flag unencrypted PHI fields, missing audit trails, and debug.log statements that output patient data. The pattern did not change. The strategy transformed how it operates.

This is the power of composable reasoning. You do not need 127 HIPAA-specific patterns. You need 1 HIPAA strategy and your existing 127 patterns all gain HIPAA awareness. The same principle applies to PCI compliance, SOX compliance, GDPR, or any domain-specific reasoning framework.

Strategy stitching turns a pattern library into a reasoning framework. The patterns define what to do. The strategies define how to think about it. The combinations are multiplicative. And the system is open: add a strategy, add a pattern, and the combinatorial space expands without touching existing code.