- name
- automations-toolkit
- description
- Build, debug, and create LeanIX Automations using built-in actions when possible and scripts only when needed. Use when creating new automations, debugging failing scripts, understanding triggers, deploying via API, converting Azure Functions, syncing subscriptions, managing tags based on relations, working with GraphQL mutations, auditing workspace automations, or transferring automation ownership. Covers trigger types, action configuration, script templates, error patterns, and multi-automation strategies.
- license
- Apache-2.0
- compatibility
- Requires LeanIX MCP server for API access (mcp__leanix__* tools)
- metadata
- {"author":"SAP LeanIX","version":"2.1.0"}
- allowed-tools
- ["Read","Write","Edit","AskUserQuestion","mcp__leanix__list_automations","mcp__leanix__get_automation","mcp__leanix__create_automation","mcp__leanix__update_automation","mcp__leanix__delete_automation","mcp__leanix__create_automation_script","mcp__leanix__get_automation_script","mcp__leanix__update_automation_script","mcp__leanix__delete_automation_script","mcp__leanix__get_automation_schema","mcp__leanix__trigger_automation","mcp__leanix__list_automation_runs","mcp__leanix__get_automation_run","mcp__leanix__get_overview","mcp__leanix__search_users"]
# LeanIX Automation Assistant
Comprehensive help for LeanIX Run Script automations: create, debug, design, optimize, and learn.
## CRITICAL: API Access
**All LeanIX API calls use MCP tools.** No shell commands, no token exchange, no curl.
- **Authentication** is handled internally by the MCP server
- **No bearer tokens** need to be managed in the skill workflow
- **No `.mcp.json` parsing** is required — MCP handles credentials automatically
---
## Anti-Patterns (Don't Do This)
| Pattern | Why It Fails |
|---------|--------------|
| `function main(data)` or `function main(context)` | `main()` takes zero parameters. `data` and `context` are injected globals at runtime. |
| `function main(){}; export { main }` (re-export) or `export default function main()` | The save-time validator requires direct export: `export function main()`, `export async function main()`, or `export const main = ...`. |
| `async function main()` with no `await` inside | `require-await` lint rule blocks save. Drop `async` if no `await`. |
| Top-level `await` outside `main()` | Rejected by TS1308. `await` only works inside the `async main()` body. |
| `import` statements | The runner blocks module imports and remote code fetches; rejected by TS2307. Only `fetch`, `data`, `context`, and standard JS built-ins are available. |
| TS-style type annotations in `.js` (e.g. `function f(x: string)`) | Rejected by TS8010. |
| Calling `Deno`, `setTimeout`, `setInterval`, `eval`, `Function`, `WebAssembly` | These globals are deleted at runtime. `ReferenceError` at execute time. |
| Relying on `console.log` for visible output | Captured to `stdout` (returned in execution result), but NOT shown prominently in the Automations UI. For visible failure, `throw new Error(...)`. |
| `relApplicationToITComponent` without wrapper | Must use `... on Application { relApplicationToITComponent { } }` |
| Mutations without `currentRev` tracking | Revision conflict errors |
| No idempotency check | Infinite loop when automation re-triggers itself |
| Using `name` for ITComponent matching | Use `displayName` to include Provider prefix |
| Returning relations/subscriptions | Return object can't update these - use GraphQL |
| Using a technical/service identity as ownerId | Shows "null null" in UI — use `set_owner_to_current_user=True` (on `update_automation` only) or a real human user's ID |
| Guessing API endpoints (e.g., `/scripts/{id}`, `/technicalUsers`) | Use MCP tools — they handle endpoints internally |
| Setting `creatorId` on template update | Immutable; silently ignored (API returns 200 but no change) |
| Investigating UUIDs before comparing with working automations | Slow; comparison-first debugging is faster |
| Re-fetching templates without caching | Redundant MCP calls; cache `list_automations()` result in context for the session |
| Building the secret key dynamically (`"default_" + "auto..."`) | Reference the secret key literally as `"default_automations_secret"` so it resolves. Dynamic construction means the secret is not attached — `context.secrets` ends up empty. |
| `LIFECYCLE_PHASE_CHANGE` trigger combined with `IGNORE_TECHNICAL_USERS` condition | Service rejects: technical-user condition is not allowed on job-type triggers. |
| Multiple actions with `startsAfter: null` (or zero such actions) | Exactly one first action is allowed per template. All others must chain via `startsAfter`. |
| Inline `script: "..."` field on an action payload | Service strips it. Always create scripts separately via `POST /scripts` and reference by `scriptId`. |
| Using `console.warn` / `console.info` / `console.debug` for diagnostics | Not captured by the runner; output is silently dropped. Only `console.log` and `console.error` are captured (to `stdout` / `stderr`). |
| Mutating `data` or `context` in place | The runner process is reused across executions and globals are restored between runs. Treat both as read-only. |
---
## Quick Reference
**Trigger limitations:**
- `Relation is removed` - The removed relation's other-end fact sheet id IS available at `data.metadata.triggerData.previousRelatedFactSheetId` (id only; best-effort/undocumented path — not part of the vendor's author API, may change). GraphQL-fetch by that id to read the removed fact sheet's fields. Reconciliation (or triggering on the target fact sheet) is optional, not required merely to identify the removed relation
- `Lifecycle state reached` - Nightly only
- `Completion score changed` - Fires on almost any edit
**Common patterns:**
```javascript
// Safe edge/node access
const items = (fs.rel?.edges || []).map(e => e?.node).filter(Boolean);
// Idempotency check
if (newValue === currentValue) return {};
// Revision tracking
currentRev = mutJson?.data?.updateFactSheet?.factSheet?.rev ?? currentRev;
```
---
## Greeting
When this skill is invoked, display this welcome message:
---
**SAP LeanIX Automation Assistant**
Welcome! I help you build, debug, and optimize LeanIX automations—using built-in actions when possible, scripts only when needed.
---
## Reference Files (Progressive Disclosure)
Load these files **only when needed** for specific workflow steps:
| File | Load When | Contains |
|------|-----------|----------|
| [`references/API-REFERENCE.md`](references/API-REFERENCE.md) | Deploying automations (Step 9) | API endpoints, DTOs, action types |
| [`references/TEMPLATES.md`](references/TEMPLATES.md) | Generating scripts (Step 7) | Ready-to-use script templates |
| [`references/LEANIX-MODEL.md`](references/LEANIX-MODEL.md) | Understanding capabilities | Fact sheet types, relations, triggers |
| [`references/NAMING-CONVENTION.md`](references/NAMING-CONVENTION.md) | Analyzing/standardizing automations | Naming convention, categories |
| [`references/WORKSPACE-ANALYSIS.md`](references/WORKSPACE-ANALYSIS.md) | Analyzing workspace automations | Full audit workflow, report format |
| [`references/MANAGE-AUTOMATIONS.md`](references/MANAGE-AUTOMATIONS.md) | Managing existing automations | Transfer, enable/disable, troubleshoot, bulk update |
| [`MCP-SETUP.md`](../../MCP-SETUP.md) | Setting up MCP connection | MCP server configuration |
---
## Workflow
### Step 0: Determine Intent
When invoked, use a two-tier `AskUserQuestion` flow to determine the user's intent:
**IMPORTANT: `AskUserQuestion` supports 2-4 options only.** Never pass more than 4 options. If more choices exist, group them or use a follow-up question.
**Question 1: What type of help do you need?**
| Option | Description |
|--------|-------------|
| **Create or build** | New automation, convert Azure Function |
| **Debug or fix** | Diagnose failing script, refactor existing |
| **Understand or learn** | Learn what automations can do |
| **Manage** | Audit workspace, transfer ownership, enable/disable, bulk update, troubleshoot |
**Question 2 (based on selection):**
| If selected | Follow-up options |
|-------------|-------------------|
| **Create or build** | "Create new automation" or "Convert Azure Function" |
| **Debug or fix** | "Debug failing script" or "Refactor/optimize script" |
| **Understand or learn** | Skip follow-up → go directly to **[Understand Capabilities] Workflow** |
| **Manage** | "Analyze workspace automations", "Transfer ownership", "Enable/disable/troubleshoot", "Bulk update" |
Branch to the appropriate workflow based on final response.
---
### Step 0.1: Verify Automations Toolset
**Run immediately after determining intent (before any other MCP call):**
Call `mcp__leanix__list_automations()`. This is a lightweight check that confirms the `automations` toolset is active.
**If the call succeeds:** Continue to the next step silently (no message needed).
**If `mcp__leanix__list_automations` is not directly available (PTD may be enabled):** Before concluding the toolset is missing, try the PTD proxy path — `call_tool(tool_name='list_automations', arguments={})`, or `search_mcp_tools('automations')` then `call_tool`. If that succeeds, PTD is working; continue silently.
**If both the direct call and the PTD proxy path fail:**
The `automations` toolset is **optional and hidden by default**. Display this message to the user:
> **Automation tools are not available.** Your MCP connection is missing the `automations` toolset.
>
> Fix: Add `?toolsets=inventory,automations` to your MCP server URL.
>
> **Claude Code (OAuth):**
> ```
> claude mcp remove leanix
> claude mcp add --transport http leanix "https://mcp.leanix.net/services/mcp-server/v1/mcp?toolsets=inventory,automations"
> ```
>
> **Claude Code (.mcp.json):** Change the URL to:
> ```
> https://{SUBDOMAIN}.leanix.net/services/mcp-server/v1/mcp?toolsets=inventory,automations
> ```
>
> After updating, restart Claude Code and re-invoke `/automations-toolkit`.
Then **stop the workflow** — do not continue without automation tools, as deployment will fail.
**If MCP is not connected at all** (no `mcp__leanix__*` tools available):
> **No LeanIX MCP connection detected.** This skill requires the LeanIX MCP server.
>
> Quickest setup:
> ```
> claude mcp add --transport http leanix "https://mcp.leanix.net/services/mcp-server/v1/mcp?toolsets=inventory,automations"
> ```
>
> See [MCP Setup](../../MCP-SETUP.md) for full instructions.
---
### Step 0.5: Schema Reference Check (Optional)
After the user selects a workflow, optionally verify schema awareness:
**Run:** `mcp__leanix__get_automation_schema()`
This returns the live trigger, condition, and action type reference from the API. Compare against `references/API-REFERENCE.md` if discrepancies are suspected.
**Key principle:** Never block the user. Schema checking is informational only.
---
## [Create New Automation] Workflow
### Step 1: Workspace Context (Automatic)
MCP handles authentication and workspace connection automatically. No credential extraction or token exchange needed.
**Verify connection:**
1. Call `mcp__leanix__get_overview()` to confirm workspace access and get basic statistics (deprecated-but-working — still directly callable; may not appear in tool-discovery catalogs)
**Get owner ID (when needed for deployment):**
- Use `mcp__leanix__search_users(email=...)` to find a specific user's UUID
- Or use `set_owner_to_current_user=True` on `update_automation` (this flag exists ONLY on `update_automation`) to assign the authenticated user as owner. For `create_automation`, omit `owner_id` (it defaults to the authenticated user) or pass an explicit `owner_id` UUID
**Display:** `Connected to LeanIX workspace - Ready for automatic deployment.`
### Step 2: Understand the Goal
Ask using `AskUserQuestion`:
**"What do you want this automation to accomplish?"**
| Option | Likely Approach |
|--------|-----------------|
| **Add/remove tags** | Built-in |
| **Set field value** | Built-in |
| **Change quality state** | Built-in |
| **Add subscription** | Built-in |
| **Create to-do/approval** | Built-in |
| **Send notification** | Built-in |
| **Multiple simple actions** | Built-in |
| **Tag based on relations** | Script |
| **Sync subscriptions** | Script |
| **Update relation attributes** | Script |
| **Calculate/aggregate** | Script |
| **Field from relations** | Script |
| **Custom conditional logic** | Script |
| **Other** | Varies |
### Step 2.5: Evaluate Action Strategy
**Decision Tree:**
```
1. Does goal require reading data from OTHER fact sheets? → Script required
2. Does goal require modifying OTHER fact sheets? → Script required
3. Does goal require conditional logic based on related data? → Script required
4. Can goal be achieved with built-in actions? → Proceed to Step 3
5. Otherwise → Skip to Step 4 (Trigger Strategy for scripts)
```
**Built-in Actions Available:**
| Action | What It Does |
|--------|--------------|
| `ADD_TAG` / `REMOVE_TAG` | Add/remove tag |
| `SET_FIELD` | Set single-select field |
| `SET_FIELD` (fieldType: `QUALITY_SEAL`) | Set quality seal |
| `ADD_SUBSCRIPTION` / `SET_SUBSCRIPTION` | Manage subscribers |
| `CREATE_ACTION_ITEM` / `CREATE_APPROVAL` | Create to-dos/approvals |
| `SEND_EMAIL_V2` / `SEND_USER_WEBHOOK` | Send notifications |
**If built-in actions suffice** → Step 3
**If script needed** → Step 4
---
### Step 3: Configure Actions (Built-in Only)
Use `AskUserQuestion` with multiSelect to select actions, then gather parameters for each.
**Email placeholders use triple braces:** `{{{factsheet.displayName}}}`, `{{{link.factsheet}}}`
**Action ordering:** Use `startsAfter` to chain actions. For approvals, use `onResolution: "ACCEPTED"` or `"REJECTED"`.
See [API Reference](references/API-REFERENCE.md) for detailed action configuration.
After configuring → Select trigger → **Step 7.5** (Deploy)
---
### Step 4: Recommend Trigger Strategy
在 GitHub 查看