apex-flow-invocation-from-apex
Use when invoking Autolaunched Flows from Apex via `Flow.Interview.createInterview`. Covers parameter typing, output retrieval, governor boundaries, and when to inline logic instead. NOT for Apex-from-Flow (`@InvocableMethod`), Process Builder, Screen Flow invocation, or Flow Orchestrator stages.
Best use case
apex-flow-invocation-from-apex is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when invoking Autolaunched Flows from Apex via `Flow.Interview.createInterview`. Covers parameter typing, output retrieval, governor boundaries, and when to inline logic instead. NOT for Apex-from-Flow (`@InvocableMethod`), Process Builder, Screen Flow invocation, or Flow Orchestrator stages.
Teams using apex-flow-invocation-from-apex should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/apex-flow-invocation-from-apex/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How apex-flow-invocation-from-apex Compares
| Feature / Agent | apex-flow-invocation-from-apex | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when invoking Autolaunched Flows from Apex via `Flow.Interview.createInterview`. Covers parameter typing, output retrieval, governor boundaries, and when to inline logic instead. NOT for Apex-from-Flow (`@InvocableMethod`), Process Builder, Screen Flow invocation, or Flow Orchestrator stages.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Apex Flow Invocation From Apex
Activates when Apex calls `Flow.Interview.createInterview` to run an Autolaunched Flow. Produces type-safe parameter maps, output retrieval, and clear guidance on the "Apex calls Flow" architectural choice.
---
## Before Starting
- Is the Flow **Autolaunched**? Only Autolaunched Flows can be started from Apex. Screen Flows cannot run headless and throw.
- Does the Flow's API name exactly match what you will pass? `Flow.Interview.createInterview` looks up by API name — a typo produces a `SObjectException` at runtime, not compile time.
- What is the **exact type** of each input variable in the Flow? Collections of SObjects, dates, currencies all have specific Apex types the Flow engine expects.
- Does the caller execute in a trigger context? Flow invocations count against SOQL, DML, and CPU governor limits of the *caller*.
- Is this a good architectural fit? If the only reason you're calling a Flow is "admin owns it," ensure the Flow's logic actually benefits from Flow's declarative shape. Plain Apex is usually simpler.
---
## Core Concepts
### The Parameter Map Must Match Flow Variable Types Exactly
`createInterview` accepts `Map<String, Object>`. The keys are Flow input-variable API names. The values are Apex primitives, SObjects, or `List<SObject>`. Mismatched types throw `Flow.FlowException` at runtime with messages like "Type mismatch: expected Decimal, got String".
Collections in Flows have two flavors — SObject collections and primitive collections. Passing `List<String>` where the Flow expects a "Collection of Text" generally works; passing `List<Opportunity>` where it expects a "Collection of SObject Records" requires the Flow's SObject type to match.
### Starting The Interview Runs The Flow
After `createInterview`, call `.start()`. This synchronously runs the Flow to completion (for Autolaunched Flows without pause elements). Long-running Flows — those with loops that create/update many records — count every action against the caller's governor limits.
### Output Variables Come Back By Name
After `.start()`, retrieve outputs with `interview.getVariableValue(name)`. The return type is `Object`; cast to the expected type. A typo in the output name returns `null` — no exception.
### Invocable Actions Are A Better Fit For Dynamic Invocation
If the caller doesn't know which Flow to run until runtime, consider registering the Flow as an Invocable Action and using the `Action` framework. This gives you discovery, validation of required parameters, and a better error surface than raw `Flow.Interview`.
---
## Common Patterns
### Pattern 1: Invoke An Autolaunched Flow With Typed Inputs And Outputs
**When to use:** Apex must delegate a calculated business rule that an admin maintains in Flow.
**How it works:**
```apex
public with sharing class TierAssignmentService {
public static String assignTier(Account a, Decimal yearToDate) {
Map<String, Object> params = new Map<String, Object>{
'inputAccount' => a,
'yearToDateAmount'=> yearToDate
};
Flow.Interview i = Flow.Interview.createInterview('Assign_Account_Tier', params);
i.start();
return (String) i.getVariableValue('resultTier');
}
}
```
**Why not the alternative:** Hardcoding the tier logic in Apex forces deploys for admin-owned tweaks. Calling the Flow preserves declarative ownership while giving Apex a clean call site.
### Pattern 2: Bulk-Safe Flow Invocation
**When to use:** A trigger fires for 200 records and each needs the Flow's logic.
**How it works:**
```apex
public with sharing class BulkTierAssignment {
public static void assignAll(List<Account> accounts, Map<Id, Decimal> ytdById) {
Map<String, Object> params = new Map<String, Object>{
'inputAccounts' => accounts,
'ytdMap' => ytdById
};
Flow.Interview i = Flow.Interview.createInterview('Bulk_Assign_Tier', params);
i.start();
}
}
```
**Why not the alternative:** Calling `createInterview` in a per-record loop multiplies CPU consumption and makes failure isolation harder. Design the Flow to accept a collection and iterate internally.
---
## Decision Guidance
| Situation | Recommended Approach | Reason |
|---|---|---|
| Admin-owned decision table (tier, routing) | Apex calls Flow | Admin maintains, Apex integrates |
| Hot-path computation in a trigger | Inline Apex | Flow adds overhead for simple math |
| Dynamic flow selection at runtime | Invocable Action framework | Adds discovery, validation, error surface |
| Flow with screen elements | Do not invoke from Apex | Screen Flows cannot run headless |
| Long-running orchestration with waits | Flow Orchestrator, not direct Apex call | Orchestrator handles waits; Flow.Interview does not |
---
## Recommended Workflow
1. Confirm the Flow is **Autolaunched** (Flow Builder → Start element → "Autolaunched Flow").
2. Read the Flow's input and output variable API names and their Apex-equivalent types.
3. Build a `Map<String, Object>` with typed keys/values.
4. Call `Flow.Interview.createInterview('Flow_API_Name', params)` — confirm exact API name.
5. Wrap `.start()` in try/catch for `Flow.FlowException` (flow-internal failures) and `DmlException` (for governor exhaustion).
6. Read outputs via `getVariableValue(name)` with a cast.
7. Add a test with `@IsTest` that arranges realistic input and asserts the output; the Apex wrapper still needs its own coverage.
---
## Review Checklist
- [ ] Flow is Autolaunched, confirmed in Setup.
- [ ] Parameter map keys match Flow variable API names exactly (case-sensitive).
- [ ] Parameter value types match Flow variable types exactly.
- [ ] `createInterview` + `start()` are wrapped in try/catch.
- [ ] Output retrieval casts to the expected Apex type.
- [ ] Invocation is NOT in a per-record loop over 200 records; Flow accepts a collection.
- [ ] Unit test covers the Apex side end-to-end.
---
## Salesforce-Specific Gotchas
See `references/gotchas.md` for the full list.
1. **Screen Flows fail at runtime** — only Autolaunched Flows start from Apex.
2. **Typo in Flow API name throws at runtime**, not compile time.
3. **Governor limits are charged to the calling transaction**, not reset by the Flow boundary.
4. **Output variable typo returns `null`** silently.
5. **Picklist values must match Flow's expected internal value**, not the label.
---
## Output Artifacts
| Artifact | Description |
|---|---|
| `references/examples.md` | Autolaunched Flow invocation, bulk-safe collection pattern |
| `references/gotchas.md` | Screen Flow failures, governor-limit sharing |
| `references/llm-anti-patterns.md` | Common LLM mistakes: hardcoded per-record loops, wrong parameter types |
| `references/well-architected.md` | Ops framing: admin ownership vs deploy cadence |
| `scripts/check_apex_flow_invocation_from_apex.py` | Stdlib lint for per-record invocation and missing try/catch |
---
## Related Skills
- **apex-invocable-method** — the inverse: exposing Apex to Flow
- **apex-trigger-architecture** — where to put the Flow invocation
- **apex-async-architecture** — when to enqueue instead of inline-invokingRelated Skills
ip-range-and-login-flow-strategy
Design and implement Salesforce Login Flows (Screen Flows assigned to profiles or Experience Cloud sites) that run post-authentication to enforce conditional MFA, IP-based branching, terms-of-service acceptance, or user data collection. Covers Login Flow creation in Flow Builder, profile/site assignment, IP-aware decision logic, and ConnectedAppPlugin extension points. NOT for static IP allowlisting or profile Login IP Ranges (see network-security-and-trusted-ips), org-wide session policies, or SSO/SAML IdP configuration.
customer-data-request-workflow
Implement GDPR/CCPA data subject rights (access, deletion, rectification) using Salesforce Privacy Center and/or custom workflow. NOT for general backup or org-level data retention policy.
apex-managed-sharing-patterns
Grant row-level access programmatically via __Share records when declarative sharing rules cannot express the policy. NOT for OWD, role hierarchy, or criteria-based sharing rule design.
omnistudio-vs-flow-decision
Use when choosing between OmniStudio (OmniScript / Integration Procedure / FlexCard / DataRaptor) and Flow / Screen Flow / Apex for a given capability. Triggers: 'omnistudio or flow', 'omniscript vs screen flow', 'integration procedure vs subflow', 'flexcard vs lightning page'. NOT for general automation selection across Workflow/Process Builder/Apex (see automation-selection tree).
lwc-in-flow-screens
Use when building, reviewing, or troubleshooting a custom Lightning Web Component that runs inside a Flow screen element, covering @api props exposed to Flow, FlowAttributeChangeEvent for output, validate() for user input validation, and flow navigation events. Triggers: 'lwc in flow screen', 'FlowAttributeChangeEvent', 'flow screen component not updating', 'flow validate method', 'flow navigation from lwc'. NOT for custom property editors (use custom-property-editor-for-flow), NOT for embedding a flow inside an LWC (use flow/screen-flows), NOT for auto-launched flows.
lwc-imperative-apex
Call Apex methods imperatively from LWC — on button click, lifecycle hooks, or conditional logic. Covers import syntax, cacheable vs non-cacheable, async/await patterns, error handling, loading states, and Promise.all. NOT for wire service (use wire-service-patterns) and NOT for testing Apex mocks (use lwc-testing).
custom-property-editor-for-flow
Use when building or reviewing an LWC Custom Property Editor for Flow screen or action configuration, including the `configurationEditor` metadata hook, builder-side APIs, validation, and value-change events. Triggers: 'custom property editor', 'Flow configuration editor', 'builderContext', 'inputVariables', 'configurationEditor'. NOT for ordinary runtime screen-component behavior when no Flow Builder design-time customization is involved.
slack-workflow-builder
Use this skill when designing or troubleshooting Slack Workflow Builder workflows that call Salesforce — especially the Salesforce connector step Run a Flow, mapping inputs/outputs, handling failures, and understanding limits. Triggers on: Slack Workflow Builder Salesforce, Run a Flow from Slack, autolaunched flow from Slack, Slack automation calling Salesforce. NOT for Salesforce Flow Builder tutorials unrelated to Slack (use flow skills), not for Flow Core Actions that send Slack messages from Salesforce (use flow-for-slack), not for initial org-to-workspace connection (use slack-salesforce-integration-setup), and not for building custom Slack apps outside Workflow Builder.
oauth-flows-and-connected-apps
Use when choosing or reviewing Salesforce OAuth flows and connected-app policy for integrations, including client credentials, JWT bearer, authorization code, device flow, scopes, and token lifecycle controls. Triggers: 'OAuth flow', 'connected app', 'client credentials', 'JWT bearer', 'refresh token', 'integration user'. NOT for record-level sharing design or for simple Named Credential usage when the auth-flow decision is already settled.
dataweave-for-apex
Use when transforming structured data inside Apex — CSV → JSON, XML → SObject list, JSON → flattened CSV, or schema-mapping a third-party payload to a Salesforce model — and the existing options (`JSON.deserialize`, `Dom.Document`, hand-written loops) are getting unwieldy. Triggers: 'apex transform csv json xml without external library', 'system.dataweave script', 'salesforce native dataweave apex execute', 'transform xml to sobject apex no mulesoft', 'json reshape salesforce apex script'. NOT for MuleSoft Anypoint DataWeave running off-platform (use mulesoft-anypoint-architecture), NOT for Apex JSON serialization basics (use apex-json-serialization), NOT for Bulk API CSV ingest (use bulk-api-2-patterns).
workflow-rule-to-flow-migration
Migrate Workflow Rules to record-triggered Flows: field update mapping, email alert migration, outbound message alternatives using Flow Core Actions, time-based workflow replacement with Scheduled Paths. NOT for Process Builder migration (use process-builder-to-flow-migration), NOT for building new flows from scratch.
subflows-and-reusability
Use when extracting reusable Flow logic into subflows, defining input and output variables, keeping parent flows maintainable, and sharing common automation contracts across multiple flows. Triggers: 'reuse this flow logic', 'how should subflow variables work', 'too much duplicated flow logic', 'subflow contract design'. NOT for Apex-called Flow execution direction or Flow Orchestration process design.