@superglue/cli 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,104 +1,138 @@
1
1
  ---
2
2
  name: superglue
3
- description: Build, test, deploy, and integrate superglue API tools via the sg CLI. Use when working with superglue tools, systems, APIs, the sg command, or integrating tools into codebases (SDK, REST API, webhooks). Covers tool configuration, credential management, OAuth, pagination, multi-step workflows, and production deployment.
3
+ description: "Build, test, deploy and integrate superglue tools via the sg CLI and superglue SDKs. IMPORTANT — you MUST invoke this skill and read the full reference BEFORE running ANY sg command or writing ANY superglue SDK/REST/webhook integration code. Before using the sg CLI, first check that it is installed (run sg --version; if not found, install with npm install -g @superglue/cli), then verify it is configured (check that sg init has been run or that SUPERGLUE_API_KEY and SUPERGLUE_API_ENDPOINT environment variables are set). If not, guide the user through setup first. After reading the SKILL.md file, also read the relevant references/ files for the specific topic (databases, file servers, transforms, integration/SDK)."
4
4
  ---
5
5
 
6
6
  # superglue CLI (`sg`) — Agent Reference
7
7
 
8
8
  ## CRITICAL RULES — READ FIRST
9
9
 
10
+ **Pre-requisites for using the CLI**
11
+
12
+ 1. **Check CLI exists**: Run `sg --version`. If it fails with `command not found`, install it: `npm install -g @superglue/cli`
13
+ 2. **Check superglue CLI config exists**: Run `sg system list`. If it fails with `fetch failed` or auth errors, the CLI needs configuration via `sg init` (see below).
14
+
10
15
  **Authentication & Credentials:**
11
16
 
12
- - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests
17
+ - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests or tool steps
13
18
  - Every request step (in tools AND `sg system call`) must include the appropriate auth header using `<<systemId_credentialKey>>` syntax
14
19
  - OAuth systems also require explicit headers — only token refresh is automatic
15
20
 
16
- **Pre-Building Testing:**
21
+ **Saving Tools:**
22
+
23
+ - **Don't save a tool without explicit user confirmation** — always ask "Should I save this tool?" first
24
+ - After `sg tool build` + `sg tool run`, present results to the user and wait for approval
25
+ - Only run `sg tool save --draft <id>` after the user explicitly confirms
26
+
27
+ **Credentials in Non-Interactive Environments (AI Agents, CI):**
17
28
 
18
- - **ALWAYS use `sg system call` to test endpoints BEFORE building tools**
19
- - Verify authentication works, understand response structure, confirm field names
20
- - Never guess API responses — test them first
21
- - This prevents 90% of tool failures
29
+ - **Pass ALL credentials (including secrets) directly via `--credentials` JSON** — do NOT use `--sensitive-credentials` (it requires an interactive TTY which agents don't have)
30
+ - Ask the user to provide secret values, then pass them in `--credentials '{"api_key":"sk-xxx"}'`
22
31
 
23
- **Example - `sg system call` with auth:**
32
+ ---
33
+
34
+ ## Installation & Setup
35
+
36
+ ### Installing the CLI
24
37
 
25
38
  ```bash
26
- sg system call --system-id notion --url "https://api.notion.com/v1/search" \
27
- --method POST \
28
- --headers '{"Authorization":"Bearer <<notion_access_token>>","Notion-Version":"2022-06-28"}' \
29
- --body '{"filter":{"property":"object","value":"page"}}'
39
+ npm install -g @superglue/cli
30
40
  ```
31
41
 
32
- **Example - Tool step with auth:**
42
+ After installation, the `sg` command is available globally.
33
43
 
34
- ```json
35
- {
36
- "headers": {
37
- "Authorization": "Bearer <<systemId_access_token>>"
38
- }
39
- }
44
+ ### Initialization (REQUIRED before first use)
45
+
46
+ The CLI **will not work** until configured with an API key. The endpoint defaults to `https://api.superglue.cloud` if not specified.
47
+
48
+ **Option A: Interactive setup (recommended for humans)**
49
+
50
+ ```bash
51
+ sg init
40
52
  ```
41
53
 
42
- **Other Critical Rules:**
54
+ This prompts for:
55
+
56
+ 1. **API Key** (required) — get one at https://app.superglue.cloud/admin?view=api-keys
57
+ 2. **API Endpoint** — defaults to `https://api.superglue.cloud`
58
+ 3. **Web Endpoint** — for OAuth callbacks, auto-derived from API endpoint
59
+ 4. **Output mode** — `stdout` (default) or `stdout+file`
60
+ 5. **Config location** — project-local (`.superglue/config.json`) or global (`~/.superglue/config.json`)
61
+
62
+ It verifies the connection before saving. On success it creates the config file, a `drafts/` directory, and updates `.gitignore` if using local config.
63
+
64
+ **Option B: Environment variables (recommended for CI and AI agents)**
65
+
66
+ If `sg init` is not practical (non-interactive environments, CI, AI agents), set these env vars instead:
67
+
68
+ ```bash
69
+ export SUPERGLUE_API_KEY="your-api-key"
70
+ export SUPERGLUE_API_ENDPOINT="https://api.superglue.cloud" # optional, this is the default
71
+ ```
72
+
73
+ With these set, all `sg` commands work without a config file.
74
+
75
+ **Option C: CLI flags (per-command override)**
76
+
77
+ ```bash
78
+ sg system list --api-key "your-key" --endpoint "https://api.superglue.cloud"
79
+ ```
80
+
81
+ ### Config Resolution Order
82
+
83
+ CLI flags > environment variables > config file (local `.superglue/config.json` > global `~/.superglue/config.json`).
43
84
 
44
- - `systemId` goes on each step's `config`, NOT at the tool level
45
- - Steps execute sequentially; each step can reference previous step results
46
- - `id` fields must be kebab-case for tools, snake_case for systems
47
- - Simple `<<varName>>` only works for **top-level keys** (no dots, no nesting)
48
- - For nested access use arrow functions: `<<(sourceData) => sourceData.currentItem.id>>`
49
- - ALWAYS access step results via `.data`: `sourceData.stepId.data` not `.results`
85
+ ### Verifying Setup
86
+
87
+ After configuring, verify the connection works:
88
+
89
+ ```bash
90
+ sg system list # should return a list (possibly empty) without errors
91
+ ```
50
92
 
51
93
  ---
52
94
 
53
95
  ## Quick Start
54
96
 
55
97
  ```bash
56
- npm install -g @superglue/cli
57
- sg init # guided setup
58
- sg system list # verify connection
98
+ sg system list
59
99
  sg tool build --config '{"id":"...","instruction":"...","steps":[...]}'
60
100
  sg tool run --draft <draftId>
61
101
  sg tool save --draft <draftId>
62
102
  ```
63
103
 
64
- **Config:** `SUPERGLUE_API_KEY` + `SUPERGLUE_API_ENDPOINT` env vars, or `.superglue/config.json` (created by `sg init`).
65
- **Priority:** CLI flags > env vars > config file.
66
-
67
104
  ## Global Flags
68
105
 
69
106
  | Flag | Description |
70
107
  | ------------------ | ------------------------------------------- |
71
108
  | `--json` | Force JSON output (auto-enabled in non-TTY) |
72
- | `-y, --yes` | Auto-accept all confirmations |
73
109
  | `--api-key <key>` | Override API key |
74
110
  | `--endpoint <url>` | Override API endpoint |
75
111
 
76
- ---
77
-
78
112
  ## Command Reference
79
113
 
80
114
  ### `sg init`
81
115
 
82
- Interactive setup — API key, endpoint, output mode, policies. Creates `.superglue/`.
116
+ Interactive setup — API key, endpoint, output mode. Creates `.superglue/`.
83
117
 
84
118
  ### Tool Commands
85
119
 
86
120
  **`sg tool build`** — Register a tool config. Returns a `draftId`. Not AI-powered — you provide the full config.
87
121
 
88
122
  ```bash
89
- sg tool build --config tool.json # from file
90
123
  sg tool build --config '{"id":"...","steps":[...]}' # inline JSON
91
124
  sg tool build --id my-tool --instruction "..." --steps steps.json --payload '{"key":"val"}'
125
+ sg tool build --config tool.json # from file
92
126
  ```
93
127
 
94
128
  | `--config <file-or-json>` | Full JSON config (file path or inline JSON string) |
95
129
  | `--id <id>` | Tool ID (kebab-case) |
96
130
  | `--instruction <text>` | Human-readable description |
97
131
  | `--steps <file>` | JSON file with steps array |
98
- | `--payload <json>` | Sample payload (generates inputSchema) |
99
- | `--file <key=path>` | Attach file reference (repeatable) |
132
+ | `--payload <json>` | Sample payload |
133
+ | `--file <key=path>` | Attach file reference |
100
134
 
101
- **`sg tool run`** — Execute a draft or saved tool.
135
+ **`sg tool run`** — Execute a draft or saved tool. Streams live execution logs to the terminal.
102
136
 
103
137
  ```bash
104
138
  sg tool run --draft <draftId> --payload '{"userId":"123"}'
@@ -114,11 +148,10 @@ sg tool run --tool my-tool --payload-file payload.json
114
148
 
115
149
  ```bash
116
150
  sg tool edit --draft <draftId> --patches '[{"op":"replace","path":"/steps/0/config/url","value":"..."}]'
117
- sg tool edit --tool my-tool --patches patches.json --test --payload '{...}'
151
+ sg tool edit --tool my-tool --patches patches.json
118
152
  ```
119
153
 
120
154
  | `--patches <json-or-file>` | JSON Patch array (inline or file) |
121
- | `--test` | Run patched tool after accepting |
122
155
 
123
156
  **`sg tool save`** — Persist draft to database. Deletes draft file on success.
124
157
 
@@ -138,33 +171,53 @@ sg tool find --id my-tool # exact ID lookup (full config)
138
171
 
139
172
  **`sg system create`**
140
173
 
174
+ **Required flags:**
175
+
176
+ - `--id <id>` — System ID (lowercase, underscores only, no hyphens)
177
+ - `--name <name>` — Human-readable display name
178
+ - `--url <url>` — API base URL (auto-filled when using `--template`)
179
+
180
+ **At least one of:**
181
+
182
+ - `--template <id>` — Pre-configured template (auto-fills name and url if not provided)
183
+ - `--url <url>` + `--name <name>` manually
184
+
185
+ **Example with credentials (non-interactive — use this in AI agent / CI contexts):**
186
+
141
187
  ```bash
142
- sg system create --id slack --template slack --sensitive-credentials client_secret
143
- sg system create --id my_api --url https://api.example.com --credentials '{"api_key":"..."}' --sensitive-credentials api_key
188
+ sg system create --id my_api --name "My API" --url https://api.example.com \
189
+ --credentials '{"api_key":"sk-xxx"}'
144
190
  ```
145
191
 
146
- | `--id <id>` | System ID (lowercase, underscores only) |
147
- | `--url <url>` | API base URL |
148
- | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
149
- | `--credentials <json>` | Non-sensitive credentials |
150
- | `--sensitive-credentials <fields>` | Comma-separated fields to prompt for securely |
151
- | `--docs-url <url>` | Documentation URL to scrape |
192
+ **With template:**
152
193
 
153
- **`sg system edit`** — Update system config or credentials.
154
- **`sg system list` / `sg system find`** — List or search systems.
194
+ ```bash
195
+ sg system create --id slack --name "Slack" --template slack
196
+ ```
197
+
198
+ **Full flag reference:**
199
+
200
+ | Flag | Description |
201
+ | ---------------------------------- | ---------------------------------------------------------------------------- |
202
+ | `--id <id>` | System ID (lowercase, underscores only) — **REQUIRED** |
203
+ | `--name <name>` | Human-readable name — **REQUIRED** |
204
+ | `--url <url>` | API base URL — **REQUIRED** (auto-filled by `--template`) |
205
+ | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
206
+ | `--credentials <json>` | Credentials JSON (use for ALL creds in non-interactive mode) |
207
+ | `--sensitive-credentials <fields>` | Comma-separated fields for masked input (TTY only — do NOT use in AI agents) |
208
+ | `--docs-url <url>` | Documentation URL to scrape |
209
+ | `--openapi-url <url>` | OpenAPI spec URL |
210
+ | `--env <environment>` | Environment: `dev` or `prod` (default: prod) |
211
+
212
+ **`sg system edit`** — Update system config or credentials. Supports `--env dev|prod`.
213
+ **`sg system list` / `sg system find`** — List or search systems. `find` supports `--env dev|prod`.
155
214
 
156
215
  **`sg system call`** — **CRITICAL for tool building.** Make authenticated calls to APIs, databases, and file servers. Use this to:
157
216
 
158
- - Test system authentication works
159
217
  - Explore API endpoints and response structures
160
218
  - Verify field names and data shapes BEFORE building tools
161
- - Debug failing tools by testing individual endpoints
162
219
 
163
220
  ```bash
164
- # Include auth header with credential placeholder
165
- sg system call --url https://api.example.com/users \
166
- --system-id my_api \
167
- --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
168
221
 
169
222
  # POST request with auth and body
170
223
  sg system call --url https://api.example.com/users \
@@ -191,12 +244,13 @@ sg system call --url "sftp://<<my_sftp_host>>:22/data" \
191
244
  | `--method <method>` | HTTP method (GET, POST, PUT, DELETE, PATCH) |
192
245
  | `--headers <json>` | HTTP headers JSON with credential placeholders |
193
246
  | `--body <string>` | Request body (JSON string) |
247
+ | `--env <env>` | Environment: `dev` or `prod` |
194
248
  | `--file <key=path>` | File references (repeatable) |
195
249
 
196
- **`sg system docs`** — Search system documentation.
250
+ **`sg system search-docs`** — Search system documentation.
197
251
 
198
252
  ```bash
199
- sg system docs --system-id slack --keywords "send message channels"
253
+ sg system search-docs --system-id slack -k "send message channels"
200
254
  ```
201
255
 
202
256
  **`sg system oauth`** — Authenticate via OAuth.
@@ -237,8 +291,7 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
237
291
  "body": "{ \"key\": \"<<payload_field>>\" }"
238
292
  },
239
293
  "dataSelector": "(sourceData) => sourceData.previousStep.data.items",
240
- "transformCode": "(items) => items.map(i => ({ id: i.id, name: i.name }))",
241
- "failureBehavior": "abort"
294
+ "failureBehavior": "fail"
242
295
  }
243
296
  ],
244
297
  "outputTransform": "(sourceData) => sourceData.stepId.data",
@@ -247,10 +300,11 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
247
300
  }
248
301
  ```
249
302
 
250
- ### Step Config Fields
303
+ ### Step Config Fields (Request Steps)
251
304
 
252
305
  | Field | Type | Description |
253
306
  | ------------- | ------ | -------------------------------------------- |
307
+ | `type` | string | `"request"` (default, can be omitted) |
254
308
  | `systemId` | string | System whose credentials to use |
255
309
  | `url` | string | Full URL with `<<variable>>` placeholders |
256
310
  | `method` | string | HTTP method |
@@ -259,13 +313,19 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
259
313
  | `body` | string | Request body (JSON string with placeholders) |
260
314
  | `pagination` | object | Auto-pagination config (see below) |
261
315
 
316
+ ### Step Config Fields (Transform Steps)
317
+
318
+ | Field | Type | Description |
319
+ | --------------- | ------ | ------------------------------------------------ |
320
+ | `type` | string | `"transform"` — **REQUIRED** for transform steps |
321
+ | `transformCode` | string | JS function: `(sourceData) => transformedData` |
322
+
262
323
  ### Step Behavior Fields
263
324
 
264
325
  | Field | Type | Description |
265
326
  | ----------------- | ------ | ------------------------------------------------ |
266
327
  | `dataSelector` | string | JS function controlling step input and loop mode |
267
- | `transformCode` | string | JS function to transform the step's response |
268
- | `failureBehavior` | string | `abort` (default), `continue`, or `skip` |
328
+ | `failureBehavior` | string | `fail` (default) or `continue` |
269
329
 
270
330
  ---
271
331
 
@@ -279,15 +339,16 @@ System credentials are namespaced as `<<systemId_credentialKey>>` and resolved s
279
339
  {"Authorization": "Bearer <<stripe_api_key>>"}
280
340
  {"Authorization": "Bearer <<gmail_access_token>>"}
281
341
  {"X-API-Key": "<<my_api_api_key>>"}
282
- {"Authorization": "Basic <<(sourceData) => Buffer.from(sourceData.my_api_username + ':' + sourceData.my_api_password).toString('base64')>>"}
342
+ {"Authorization": "Basic <<my_api_username>>:<<my_api_password>>"}
283
343
  ```
284
344
 
345
+ Basic auth is auto-encoded: if the value after `Basic ` isn't already base64, the engine encodes it automatically.
346
+
285
347
  ### Credential Lifecycle
286
348
 
287
349
  - Non-sensitive creds (`client_id`, `auth_url`, etc.) are stored via `--credentials`
288
- - Sensitive creds (`api_key`, `client_secret`) use `--sensitive-credentials` for secure input
350
+ - Sensitive creds (`api_key`, `client_secret`) — in non-interactive mode (AI agents, CI), pass via `--credentials` JSON. In interactive TTY, use `--sensitive-credentials` for masked input, or set `SUPERGLUE_CRED_<FIELD>` env vars.
289
351
  - OAuth tokens (`access_token`, `refresh_token`) are auto-refreshed before each step execution
290
- - Placeholders like `<<gmail_access_token>>` always resolve to the current (refreshed) token
291
352
 
292
353
  ---
293
354
 
@@ -301,7 +362,6 @@ All step config fields support `<<variable>>` placeholders:
301
362
  | -------------------------- | --------------------------- |
302
363
  | `<<fieldName>>` | Payload field or credential |
303
364
  | `<<systemId_credKey>>` | System credential |
304
- | `<<stepId.data.field>>` | Previous step result |
305
365
  | `<<(sourceData) => expr>>` | JavaScript expression |
306
366
 
307
367
  **CRITICAL**: Simple `<<varName>>` only works for **top-level keys**. No dots, no nesting.
@@ -360,16 +420,8 @@ sourceData.stepId = [
360
420
  { currentItem: <item2>, data: <response2>, success: true },
361
421
  ...
362
422
  ]
363
- // Access all responses:
364
- sourceData.stepId.map(item => item.data)
365
- // Nested arrays:
366
- sourceData.stepId.flatMap(item => item.data.results)
367
- // Only successes:
368
- sourceData.stepId.filter(item => item.success).map(i => i.data)
369
423
  ```
370
424
 
371
- **NEVER** access step results without `.data` — `sourceData.stepId.results` hits the envelope, not the API response. Use `sourceData.stepId.data.results`.
372
-
373
425
  ### Data Selectors
374
426
 
375
427
  Control what a step receives as input and whether it loops:
@@ -384,14 +436,46 @@ In loop mode, `sourceData.currentItem` is set to the current array element.
384
436
 
385
437
  Empty arrays are valid — the step simply skips execution.
386
438
 
387
- ### Step Result References (in `<<>>` placeholders)
439
+ ### Two Step Types
440
+
441
+ **Request step** (HTTP, Postgres, FTP/SFTP/SMB) — makes an API call:
388
442
 
443
+ ```json
444
+ {
445
+ "id": "get-users",
446
+ "config": {
447
+ "type": "request",
448
+ "systemId": "my_api",
449
+ "url": "https://api.example.com/users",
450
+ "method": "GET",
451
+ "headers": { "Authorization": "Bearer <<my_api_access_token>>" }
452
+ }
453
+ }
389
454
  ```
390
- <<stepId.data>> — full response data (object-selector step)
391
- <<stepId.data.field>> — nested field
392
- <<stepId.data.items[0].id>> — array element
455
+
456
+ **Transform step** — pure JavaScript, no API call. Use when a subsequent request step needs reshaped data:
457
+
458
+ ```json
459
+ {
460
+ "id": "format-data",
461
+ "config": {
462
+ "type": "transform",
463
+ "transformCode": "(sourceData) => sourceData.getUsers.data.map(u => ({ id: u.id, name: u.fullName }))"
464
+ }
465
+ }
393
466
  ```
394
467
 
468
+ Transform steps do NOT have: `systemId`, `url`, `method`, `headers`, `body`, `queryParams`, or `pagination`. The `transformCode` function receives `sourceData` (same object available everywhere) and its return value becomes `.data` in the step envelope.
469
+
470
+ **When to use each:**
471
+
472
+ | Need | Use |
473
+ | ------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
474
+ | Filter/reshape data for a SUBSEQUENT request step | Transform step (`config.type: "transform"`) |
475
+ | Shape the final tool output | `outputTransform` (runs after all steps, has a slightly different schema than transform only steps) |
476
+ | Select input / control looping for a step | `dataSelector` on the step |
477
+ | Inline data computation in URL/body/headers | `<<(sourceData) => ...>>` expressions |
478
+
395
479
  ### Execution Pipeline
396
480
 
397
481
  For each step in order:
@@ -399,50 +483,10 @@ For each step in order:
399
483
  1. Build `sourceData`: `{ ...originalPayload, ...previousStepResults, ...credentials }`
400
484
  2. Run `dataSelector(sourceData)` → determines single vs loop execution
401
485
  3. For each item: merge `currentItem` into `sourceData`, resolve `<<>>` variables, execute step
402
- 4. `transformCode` runs on the raw response → output becomes `.data` in the envelope
403
- 5. Wrap result: `{ currentItem, data, success }` and store in `sourceData[stepId]`
404
- 6. After all steps: run `outputTransform(sourceData)` to shape final output
405
-
406
- ### Complete Example: List-then-Detail Pattern
407
-
408
- A tool that lists Gmail message IDs, then fetches details for each:
409
-
410
- ```json
411
- {
412
- "id": "get-recent-emails",
413
- "instruction": "Fetches the 10 most recent Gmail emails with subject, sender, and snippet",
414
- "steps": [
415
- {
416
- "id": "list-messages",
417
- "config": {
418
- "systemId": "gmail",
419
- "url": "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10",
420
- "method": "GET",
421
- "headers": { "Authorization": "Bearer <<gmail_access_token>>" }
422
- }
423
- },
424
- {
425
- "id": "get-details",
426
- "dataSelector": "(sourceData) => sourceData[\"list-messages\"].data.messages.map(m => m.id)",
427
- "config": {
428
- "systemId": "gmail",
429
- "url": "https://gmail.googleapis.com/gmail/v1/users/me/messages/<<currentItem>>?format=metadata&metadataHeaders=Subject&metadataHeaders=From&metadataHeaders=Date",
430
- "method": "GET",
431
- "headers": { "Authorization": "Bearer <<gmail_access_token>>" }
432
- }
433
- }
434
- ],
435
- "outputTransform": "(sourceData) => sourceData[\"get-details\"].map(item => { var h = item.data.payload.headers; var get = function(n) { var f = h.find(function(x) { return x.name === n; }); return f ? f.value : null; }; return { id: item.data.id, subject: get(\"Subject\"), from: get(\"From\"), date: get(\"Date\"), snippet: item.data.snippet }; })"
436
- }
437
- ```
438
-
439
- What happens at runtime:
440
-
441
- 1. **list-messages** runs once (no dataSelector) → `sourceData["list-messages"] = { currentItem: {}, data: { messages: [{id: "abc"}, {id: "def"}, ...] }, success: true }`
442
- 2. **get-details** dataSelector returns `["abc", "def", ...]` (an array) → step loops over each ID
443
- 3. Each loop iteration sets `currentItem` to the string ID, which `<<currentItem>>` injects into the URL
444
- 4. Loop results stored as: `sourceData["get-details"] = [{ currentItem: "abc", data: {id, snippet, payload...}, success }, ...]`
445
- 5. **outputTransform** maps over the array of envelopes, extracting `.data` fields from each
486
+ - **Request step**: makes the HTTP/DB/FTP call, raw response becomes `.data`
487
+ - **Transform step**: runs `transformCode(sourceData)`, return value becomes `.data`
488
+ 4. Wrap result: `{ currentItem, data, success }` and store in `sourceData[stepId]`
489
+ 5. After all steps: run `outputTransform(sourceData)` to shape final output
446
490
 
447
491
  ---
448
492
 
@@ -469,23 +513,14 @@ What happens at runtime:
469
513
 
470
514
  All types stop when `stopCondition` returns true, response is empty, or max pages reached.
471
515
 
472
- ### Common Auth Patterns by Service Type
473
-
474
- | Service | Header |
475
- | ---------------------------- | ----------------------------------------------------- |
476
- | OAuth (Google, GitHub, etc.) | `"Authorization": "Bearer <<systemId_access_token>>"` |
477
- | API Key (Stripe, etc.) | `"Authorization": "Bearer <<systemId_api_key>>"` |
478
- | API Key in header | `"X-API-Key": "<<systemId_api_key>>"` |
479
-
480
- ---
481
-
482
516
  ## Systems
483
517
 
484
518
  ### Credential Model
485
519
 
486
- - `credentials` — non-sensitive config stored directly (client_id, auth_url, scopes, etc.)
487
- - `sensitiveCredentials` — secrets requiring secure UI input (api_key, client_secret)
488
- - **NEVER ask users to paste secrets in chat** — always use `--sensitive-credentials`
520
+ - `credentials` — all credentials passed as JSON via `--credentials`
521
+ - `sensitiveCredentials` — interactive masked prompt for secrets (TTY only, NOT for AI agents or CI)
522
+ - **For AI agents / non-interactive use:** pass ALL credentials (including secrets like api_key, client_secret) directly via `--credentials '{"api_key":"..."}'`. Ask the user to provide the secret values, then include them in the JSON.
523
+ - **For human interactive use:** use `--sensitive-credentials` for masked input of secrets
489
524
 
490
525
  ### Templates
491
526
 
@@ -508,85 +543,12 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
508
543
 
509
544
  ## Debugging Failed Tools
510
545
 
511
- ### Common Errors and Fixes
512
-
513
- | Error | Cause | Fix |
514
- | --------------------- | ---------------------------------- | ------------------------------------------------------------------------- |
515
- | 401 Unauthorized | Missing or invalid auth header | Add `"Authorization": "Bearer <<systemId_access_token>>"` to step headers |
516
- | 403 Forbidden | Wrong scopes or permissions | Check OAuth scopes, re-authenticate |
517
- | Empty `data: {}` | No outputTransform or dataSelector | Add `outputTransform` to extract from step results |
518
- | Variable not resolved | Wrong placeholder syntax | Check `<<systemId_credKey>>` matches actual credential keys |
519
- | Step references empty | Wrong step ID in reference | Verify `<<stepId.data.field>>` matches actual step IDs |
520
-
521
546
  ### Debug Workflow
522
547
 
523
548
  1. Run with `--include-step-results` to see raw step responses
524
549
  2. Check each step's `data` field — is the API returning what you expect?
525
550
  3. Verify credential placeholders match `sg system find --id <systemId>` placeholder list
526
- 4. **Test API calls directly with `sg system call`** — isolate whether the issue is auth, endpoint, or transform:
527
- ```bash
528
- # Test the exact URL from your failing step
529
- sg system call --url "https://api.example.com/endpoint" \
530
- --system-id my_api \
531
- --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
532
- ```
533
- 5. Compare `sg system call` response to what your tool expects — fix transforms accordingly
534
-
535
- ### Self-Healing Pattern
536
-
537
- When an outputTransform or dataSelector fails, the executor retries with an LLM-generated fix. To help this:
538
-
539
- - Throw descriptive errors: `throw new Error("Expected array at data.items, got: " + typeof data.items)`
540
- - Check for null/undefined with `?.` and defaults
541
- - Validate arrays with `Array.isArray()` before calling array methods
542
-
543
- ---
544
-
545
- ## Workflow Guide
546
-
547
- ### Pre-Building: Test with `sg system call`
548
-
549
- **ALWAYS test endpoints with `sg system call` before building tools.** This is the most important step to avoid broken tools.
550
-
551
- 1. **Verify authentication** — Test that credentials work:
552
-
553
- ```bash
554
- sg system call --url "https://api.example.com/me" \
555
- --system-id my_api \
556
- --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
557
- ```
558
-
559
- 2. **Explore response structure** — Understand what the API returns:
560
-
561
- ```bash
562
- sg system call --url "https://api.example.com/users?limit=2" \
563
- --system-id my_api \
564
- --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
565
- ```
566
-
567
- Look at the response to understand:
568
- - Where is the data array? (`data.users`, `data.items`, `data.results`?)
569
- - What fields are available? (exact field names matter!)
570
- - Is there pagination info? (`nextCursor`, `hasMore`, `total`?)
571
-
572
- 3. **Test the exact endpoints your tool will use** — Don't guess:
573
- ```bash
574
- # If your tool will fetch user details by ID:
575
- sg system call --url "https://api.example.com/users/123" \
576
- --system-id my_api \
577
- --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
578
- ```
579
-
580
- ### Full Workflow
581
-
582
- 1. **Create system** → `sg system create --id my_api --url ... --sensitive-credentials api_key`
583
- 2. **Authenticate** → `sg system oauth` (if OAuth) or credentials are already set
584
- 3. **Test auth** → `sg system call` to verify credentials work
585
- 4. **Explore API** → `sg system docs` + more `sg system call` to test endpoints
586
- 5. **Build tool** → Construct full config JSON, `sg tool build --config '...'`
587
- 6. **Test** → `sg tool run --draft <id> --include-step-results`
588
- 7. **Iterate** → `sg tool edit --draft <id> --patches '[...]' --test`
589
- 8. **Save** → `sg tool save --draft <id>`
551
+ 4. **Test API calls directly with `sg system call`** — isolate whether the issue is auth, endpoint, or transform
590
552
 
591
553
  ---
592
554
 
@@ -613,21 +575,24 @@ curl -X POST "https://api.superglue.cloud/v1/hooks/{toolId}?token=$SUPERGLUE_API
613
575
 
614
576
  ```typescript
615
577
  import { configure, runTool } from "@superglue/client";
616
- configure({ apiKey: process.env.SUPERGLUE_API_KEY });
617
- const { data } = await runTool("my-tool-id", { inputs: { userId: "123" } });
578
+ configure({ apiKey: process.env.SUPERGLUE_API_KEY!, baseUrl: "https://api.superglue.cloud/v1" });
579
+ const response = await runTool("my-tool-id", { inputs: { userId: "123" } });
580
+ // response.data is a Run object: { runId, toolId, status, data, error, metadata }
618
581
  ```
619
582
 
620
583
  ### Python SDK
621
584
 
622
585
  ```python
623
586
  import os
624
- from superglue_client import SuperglueClient
587
+ from superglue_client import AuthenticatedClient
625
588
  from superglue_client.api.tools import run_tool
626
- client = SuperglueClient(base_url="https://api.superglue.cloud/v1", token=os.environ["SUPERGLUE_API_KEY"])
627
- result = run_tool.sync(client=client, tool_id="my-tool-id", body={"inputs": {"userId": "123"}})
628
- ```
589
+ from superglue_client.models.run_request import RunRequest
590
+ from superglue_client.models.run_request_inputs import RunRequestInputs
629
591
 
630
- **For complete integration patterns** (error handling, retries, webhooks, async execution), read `references/integration.md`.
592
+ client = AuthenticatedClient(base_url="https://api.superglue.cloud/v1", token=os.environ["SUPERGLUE_API_KEY"])
593
+ with client as c:
594
+ result = run_tool.sync("my-tool-id", client=c, body=RunRequest(inputs=RunRequestInputs.from_dict({"userId": "123"})))
595
+ ```
631
596
 
632
597
  ---
633
598
 
@@ -657,19 +622,3 @@ Attach files with `--file key=path`. Reference in payloads with `file::<key>`. A
657
622
  ```bash
658
623
  sg tool run --draft <id> --payload '{"data": "file::mysheet"}' --file mysheet=data.xlsx
659
624
  ```
660
-
661
- ## Configuration
662
-
663
- `.superglue/config.json`:
664
-
665
- ```json
666
- {
667
- "apiKey": "...",
668
- "endpoint": "https://api.superglue.cloud",
669
- "output": { "mode": "stdout", "directory": ".superglue/output" },
670
- "policies": { "callSystem": "ask_every_time", "editTool": "confirm" }
671
- }
672
- ```
673
-
674
- **callSystem:** `ask_every_time` | `run_gets_only` | `run_everything`
675
- **editTool:** `confirm` | `auto_accept`
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "superglue"
3
+ short_description: "Build, test, deploy, and integrate superglue API tools via the sg CLI and SDK"
4
+ icon_small: "./assets/superglue.png"
5
+ icon_large: "./assets/superglue.png"
6
+ brand_color: "#FFA500"
7
+ default_prompt: "I need help building a superglue integration tool"