@superglue/cli 1.0.0 → 1.1.1

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.
@@ -0,0 +1,740 @@
1
+ ---
2
+ name: superglue
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
+ ---
5
+
6
+ # superglue CLI (`sg`) — Agent Reference
7
+
8
+ ## CRITICAL RULES — READ FIRST
9
+
10
+ **Authentication & Credentials:**
11
+
12
+ - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests
13
+ - Every request step (in tools AND `sg system call`) must include the appropriate auth header using `<<systemId_credentialKey>>` syntax
14
+ - OAuth systems also require explicit headers — only token refresh is automatic
15
+
16
+ **Pre-Building Testing:**
17
+
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
22
+
23
+ **Example - `sg system call` with auth:**
24
+
25
+ ```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"}}'
30
+ ```
31
+
32
+ **Example - Tool step with auth:**
33
+
34
+ ```json
35
+ {
36
+ "headers": {
37
+ "Authorization": "Bearer <<systemId_access_token>>"
38
+ }
39
+ }
40
+ ```
41
+
42
+ **Other Critical Rules:**
43
+
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`
50
+
51
+ ---
52
+
53
+ ## Installation & Setup
54
+
55
+ ### Prerequisites Check
56
+
57
+ Before running any `sg` command, verify the CLI is installed and configured:
58
+
59
+ 1. **Check CLI exists**: Run `sg --version`. If it fails with `command not found`, install it: `npm install -g @superglue/cli`
60
+ 2. **Check config exists**: Run `sg system list`. If it fails with `fetch failed` or auth errors, the CLI needs configuration (see below).
61
+
62
+ ### Installing the CLI
63
+
64
+ ```bash
65
+ npm install -g @superglue/cli
66
+ ```
67
+
68
+ After installation, the `sg` command is available globally.
69
+
70
+ ### Initialization (REQUIRED before first use)
71
+
72
+ The CLI **will not work** until configured with an API key and endpoint. Without configuration, all commands fail with `fetch failed` or similar connection errors.
73
+
74
+ **Option A: Interactive setup (recommended for humans)**
75
+
76
+ ```bash
77
+ sg init
78
+ ```
79
+
80
+ This prompts for:
81
+
82
+ 1. **API Key** (required) — get one at https://app.superglue.cloud/admin?view=api-keys
83
+ 2. **API Endpoint** — defaults to `https://api.superglue.cloud`
84
+ 3. **Web Endpoint** — for OAuth callbacks, auto-derived from API endpoint
85
+ 4. **Output mode** — `stdout` (default) or `stdout+file`
86
+ 5. **Config location** — project-local (`.superglue/config.json`) or global (`~/.superglue/config.json`)
87
+
88
+ It verifies the connection before saving. On success it creates the config file, a `drafts/` directory, and updates `.gitignore` if using local config.
89
+
90
+ **Option B: Environment variables (recommended for CI and AI agents)**
91
+
92
+ If `sg init` is not practical (non-interactive environments, CI, AI agents), set these env vars instead:
93
+
94
+ ```bash
95
+ export SUPERGLUE_API_KEY="your-api-key"
96
+ export SUPERGLUE_API_ENDPOINT="https://api.superglue.cloud" # optional, this is the default
97
+ ```
98
+
99
+ With these set, all `sg` commands work without a config file.
100
+
101
+ **Option C: CLI flags (per-command override)**
102
+
103
+ ```bash
104
+ sg system list --api-key "your-key" --endpoint "https://api.superglue.cloud"
105
+ ```
106
+
107
+ ### Config Resolution Order
108
+
109
+ CLI flags > environment variables > config file (local `.superglue/config.json` > global `~/.superglue/config.json`).
110
+
111
+ ### Verifying Setup
112
+
113
+ After configuring, verify the connection works:
114
+
115
+ ```bash
116
+ sg system list # should return a list (possibly empty) without errors
117
+ ```
118
+
119
+ If you see `fetch failed`, `ECONNREFUSED`, or authentication errors, double-check your API key and endpoint.
120
+
121
+ ---
122
+
123
+ ## Quick Start
124
+
125
+ ```bash
126
+ sg system list # verify connection
127
+ sg tool build --config '{"id":"...","instruction":"...","steps":[...]}'
128
+ sg tool run --draft <draftId>
129
+ sg tool save --draft <draftId>
130
+ ```
131
+
132
+ ## Global Flags
133
+
134
+ | Flag | Description |
135
+ | ------------------ | ------------------------------------------- |
136
+ | `--json` | Force JSON output (auto-enabled in non-TTY) |
137
+ | `--api-key <key>` | Override API key |
138
+ | `--endpoint <url>` | Override API endpoint |
139
+
140
+ ---
141
+
142
+ ## Command Reference
143
+
144
+ ### `sg init`
145
+
146
+ Interactive setup — API key, endpoint, output mode. Creates `.superglue/`.
147
+
148
+ ### Tool Commands
149
+
150
+ **`sg tool build`** — Register a tool config. Returns a `draftId`. Not AI-powered — you provide the full config.
151
+
152
+ ```bash
153
+ sg tool build --config tool.json # from file
154
+ sg tool build --config '{"id":"...","steps":[...]}' # inline JSON
155
+ sg tool build --id my-tool --instruction "..." --steps steps.json --payload '{"key":"val"}'
156
+ ```
157
+
158
+ | `--config <file-or-json>` | Full JSON config (file path or inline JSON string) |
159
+ | `--id <id>` | Tool ID (kebab-case) |
160
+ | `--instruction <text>` | Human-readable description |
161
+ | `--steps <file>` | JSON file with steps array |
162
+ | `--payload <json>` | Sample payload (generates inputSchema) |
163
+ | `--file <key=path>` | Attach file reference (repeatable) |
164
+
165
+ **`sg tool run`** — Execute a draft or saved tool. Streams live execution logs to the terminal.
166
+
167
+ ```bash
168
+ sg tool run --draft <draftId> --payload '{"userId":"123"}'
169
+ sg tool run --tool my-tool --payload-file payload.json
170
+ ```
171
+
172
+ | `--draft <id>` / `--tool <id>` | Draft ID or saved tool ID |
173
+ | `--payload <json>` / `--payload-file <path>` | Payload |
174
+ | `--include-step-results` | Include raw step results |
175
+ | `--include-config` | Include full tool config |
176
+
177
+ **`sg tool edit`** — Apply JSON Patch (RFC 6902) operations.
178
+
179
+ ```bash
180
+ sg tool edit --draft <draftId> --patches '[{"op":"replace","path":"/steps/0/config/url","value":"..."}]'
181
+ sg tool edit --tool my-tool --patches patches.json --test --payload '{...}'
182
+ ```
183
+
184
+ | `--patches <json-or-file>` | JSON Patch array (inline or file) |
185
+ | `--test` | Run patched tool after accepting |
186
+
187
+ **`sg tool save`** — Persist draft to database. Deletes draft file on success.
188
+
189
+ ```bash
190
+ sg tool save --draft <draftId>
191
+ ```
192
+
193
+ **`sg tool list` / `sg tool find`**
194
+
195
+ ```bash
196
+ sg tool list # all non-archived tools
197
+ sg tool find "shopify orders" # search (compact results)
198
+ sg tool find --id my-tool # exact ID lookup (full config)
199
+ ```
200
+
201
+ ### System Commands
202
+
203
+ **`sg system create`**
204
+
205
+ ```bash
206
+ sg system create --id slack --template slack --sensitive-credentials client_secret
207
+ sg system create --id my_api --url https://api.example.com --credentials '{"api_key":"..."}' --sensitive-credentials api_key
208
+ ```
209
+
210
+ | `--id <id>` | System ID (lowercase, underscores only) |
211
+ | `--url <url>` | API base URL |
212
+ | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
213
+ | `--credentials <json>` | Non-sensitive credentials |
214
+ | `--sensitive-credentials <fields>` | Comma-separated fields to prompt for securely |
215
+ | `--docs-url <url>` | Documentation URL to scrape |
216
+ | `--env <environment>` | Environment: `dev` or `prod` (default: prod) |
217
+
218
+ **`sg system edit`** — Update system config or credentials. Supports `--env dev|prod`.
219
+ **`sg system list` / `sg system find`** — List or search systems. `find` supports `--env dev|prod`.
220
+
221
+ **`sg system call`** — **CRITICAL for tool building.** Make authenticated calls to APIs, databases, and file servers. Use this to:
222
+
223
+ - Test system authentication works
224
+ - Explore API endpoints and response structures
225
+ - Verify field names and data shapes BEFORE building tools
226
+ - Debug failing tools by testing individual endpoints
227
+
228
+ ```bash
229
+ # Include auth header with credential placeholder
230
+ sg system call --url https://api.example.com/users \
231
+ --system-id my_api \
232
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
233
+
234
+ # POST request with auth and body
235
+ sg system call --url https://api.example.com/users \
236
+ --system-id my_api \
237
+ --method POST \
238
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}' \
239
+ --body '{"name":"test"}'
240
+
241
+ # Database query (Postgres)
242
+ sg system call --url "postgres://<<my_db_host>>:5432/mydb" \
243
+ --system-id my_db \
244
+ --body '{"query":"SELECT * FROM users LIMIT 5"}'
245
+
246
+ # File server (SFTP)
247
+ sg system call --url "sftp://<<my_sftp_host>>:22/data" \
248
+ --system-id my_sftp \
249
+ --body '{"operation":"list","path":"/"}'
250
+ ```
251
+
252
+ | Flag | Description |
253
+ | ------------------- | --------------------------------------------------------- |
254
+ | `--url <url>` | Full URL with protocol (http/https/postgres/sftp/ftp/smb) |
255
+ | `--system-id <id>` | System ID for credential injection |
256
+ | `--method <method>` | HTTP method (GET, POST, PUT, DELETE, PATCH) |
257
+ | `--headers <json>` | HTTP headers JSON with credential placeholders |
258
+ | `--body <string>` | Request body (JSON string) |
259
+ | `--env <env>` | Environment: `dev` or `prod` |
260
+ | `--file <key=path>` | File references (repeatable) |
261
+
262
+ **`sg system search-docs`** — Search system documentation.
263
+
264
+ ```bash
265
+ sg system search-docs --system-id slack -k "send message channels"
266
+ ```
267
+
268
+ **`sg system oauth`** — Authenticate via OAuth.
269
+
270
+ ```bash
271
+ sg system oauth --system-id gmail --scopes "https://www.googleapis.com/auth/gmail.readonly"
272
+ sg system oauth --system-id my_api --grant-type client_credentials --scopes "read write"
273
+ ```
274
+
275
+ | `--system-id <id>` | Required |
276
+ | `--scopes <scopes>` | Space-separated OAuth scopes (required) |
277
+ | `--grant-type <type>` | `authorization_code` (default) or `client_credentials` |
278
+
279
+ ### Run Commands
280
+
281
+ **`sg run list`** — List execution runs. Filter by `--tool`, `--status`, `--source`, `--limit`.
282
+ **`sg run get <runId>`** — Get run details. `--fetch-results` to include data.
283
+
284
+ ---
285
+
286
+ ## Tool Configuration — Full Schema
287
+
288
+ ```json
289
+ {
290
+ "id": "kebab-case-tool-name",
291
+ "instruction": "Brief human-readable description of what this tool does",
292
+ "steps": [
293
+ {
294
+ "id": "unique-step-id",
295
+ "config": {
296
+ "systemId": "example_system",
297
+ "url": "https://api.example.com/endpoint?param=<<payload_field>>",
298
+ "method": "GET",
299
+ "headers": {
300
+ "Authorization": "Bearer <<example_system_access_token>>"
301
+ },
302
+ "queryParams": { "limit": "10" },
303
+ "body": "{ \"key\": \"<<payload_field>>\" }"
304
+ },
305
+ "dataSelector": "(sourceData) => sourceData.previousStep.data.items",
306
+ "transformCode": "(items) => items.map(i => ({ id: i.id, name: i.name }))",
307
+ "failureBehavior": "abort"
308
+ }
309
+ ],
310
+ "outputTransform": "(sourceData) => sourceData.stepId.data",
311
+ "outputSchema": { "type": "object", "properties": {} },
312
+ "inputSchema": { "type": "object", "properties": {} }
313
+ }
314
+ ```
315
+
316
+ ### Step Config Fields
317
+
318
+ | Field | Type | Description |
319
+ | ------------- | ------ | -------------------------------------------- |
320
+ | `systemId` | string | System whose credentials to use |
321
+ | `url` | string | Full URL with `<<variable>>` placeholders |
322
+ | `method` | string | HTTP method |
323
+ | `headers` | object | HTTP headers with credential placeholders |
324
+ | `queryParams` | object | URL query parameters |
325
+ | `body` | string | Request body (JSON string with placeholders) |
326
+ | `pagination` | object | Auto-pagination config (see below) |
327
+
328
+ ### Step Behavior Fields
329
+
330
+ | Field | Type | Description |
331
+ | ----------------- | ------ | ------------------------------------------------ |
332
+ | `dataSelector` | string | JS function controlling step input and loop mode |
333
+ | `transformCode` | string | JS function to transform the step's response |
334
+ | `failureBehavior` | string | `abort` (default), `continue`, or `skip` |
335
+
336
+ ---
337
+
338
+ ## Credential Placeholders
339
+
340
+ System credentials are namespaced as `<<systemId_credentialKey>>` and resolved server-side at execution time. **You MUST explicitly reference them in headers.**
341
+
342
+ ### Auth Header Patterns
343
+
344
+ ```json
345
+ {"Authorization": "Bearer <<stripe_api_key>>"}
346
+ {"Authorization": "Bearer <<gmail_access_token>>"}
347
+ {"X-API-Key": "<<my_api_api_key>>"}
348
+ {"Authorization": "Basic <<(sourceData) => Buffer.from(sourceData.my_api_username + ':' + sourceData.my_api_password).toString('base64')>>"}
349
+ ```
350
+
351
+ ### Credential Lifecycle
352
+
353
+ - Non-sensitive creds (`client_id`, `auth_url`, etc.) are stored via `--credentials`
354
+ - Sensitive creds (`api_key`, `client_secret`) use `--sensitive-credentials` for secure input
355
+ - OAuth tokens (`access_token`, `refresh_token`) are auto-refreshed before each step execution
356
+ - Placeholders like `<<gmail_access_token>>` always resolve to the current (refreshed) token
357
+
358
+ ---
359
+
360
+ ## Variables and Data Flow
361
+
362
+ ### Variable Syntax
363
+
364
+ All step config fields support `<<variable>>` placeholders:
365
+
366
+ | Syntax | Resolves to |
367
+ | -------------------------- | --------------------------- |
368
+ | `<<fieldName>>` | Payload field or credential |
369
+ | `<<systemId_credKey>>` | System credential |
370
+ | `<<stepId.data.field>>` | Previous step result |
371
+ | `<<(sourceData) => expr>>` | JavaScript expression |
372
+
373
+ **CRITICAL**: Simple `<<varName>>` only works for **top-level keys**. No dots, no nesting.
374
+
375
+ - VALID: `<<userId>>`, `<<currentItem>>`, `<<stripe_api_key>>`
376
+ - INVALID: `<<currentItem.id>>`, `<<sourceData.userId>>` — these FAIL at runtime
377
+
378
+ For nested access, use arrow functions: `<<(sourceData) => sourceData.currentItem.id>>`
379
+
380
+ ### sourceData Object
381
+
382
+ `sourceData` is the cumulative state available to all JS expressions (data selectors, transforms, variable expressions):
383
+
384
+ ```javascript
385
+ sourceData = {
386
+ // Payload fields at ROOT level (NEVER use sourceData.payload.*)
387
+ userId: "123",
388
+ date: "2024-01-15",
389
+
390
+ // Previous step results, keyed by step ID
391
+ // Object-selector step:
392
+ getUsers: { currentItem: {}, data: { users: [...] }, success: true },
393
+ // Array-selector (loop) step:
394
+ fetchDetails: [
395
+ { currentItem: "id1", data: { name: "Alice" }, success: true },
396
+ { currentItem: "id2", data: { name: "Bob" }, success: true },
397
+ ],
398
+
399
+ // Current loop item (only set inside a looping step's config)
400
+ currentItem: { id: 1 },
401
+
402
+ // Credentials (flattened, namespaced)
403
+ systemId_access_token: "...",
404
+ systemId_api_key: "..."
405
+ }
406
+ ```
407
+
408
+ ### Step Result Envelope
409
+
410
+ **Every** step result is wrapped in an envelope — you MUST account for this.
411
+
412
+ **Object selector (or no selector)** — step runs once:
413
+
414
+ ```javascript
415
+ sourceData.stepId = { currentItem: <selectorOutput>, data: <apiResponse>, success: true }
416
+ // Access the API response:
417
+ sourceData.stepId.data
418
+ sourceData.stepId.data.users
419
+ ```
420
+
421
+ **Array selector** — step loops, result is an array of envelopes:
422
+
423
+ ```javascript
424
+ sourceData.stepId = [
425
+ { currentItem: <item1>, data: <response1>, success: true },
426
+ { currentItem: <item2>, data: <response2>, success: true },
427
+ ...
428
+ ]
429
+ // Access all responses:
430
+ sourceData.stepId.map(item => item.data)
431
+ // Nested arrays:
432
+ sourceData.stepId.flatMap(item => item.data.results)
433
+ // Only successes:
434
+ sourceData.stepId.filter(item => item.success).map(i => i.data)
435
+ ```
436
+
437
+ **NEVER** access step results without `.data` — `sourceData.stepId.results` hits the envelope, not the API response. Use `sourceData.stepId.data.results`.
438
+
439
+ ### Data Selectors
440
+
441
+ Control what a step receives as input and whether it loops:
442
+
443
+ | Return type | Behavior |
444
+ | ------------------ | ----------------------------------- |
445
+ | Single object | Step runs once with that object |
446
+ | Array | Step runs once per item (loop mode) |
447
+ | `undefined`/`null` | Step receives full sourceData |
448
+
449
+ In loop mode, `sourceData.currentItem` is set to the current array element.
450
+
451
+ Empty arrays are valid — the step simply skips execution.
452
+
453
+ ### Step Result References (in `<<>>` placeholders)
454
+
455
+ ```
456
+ <<stepId.data>> — full response data (object-selector step)
457
+ <<stepId.data.field>> — nested field
458
+ <<stepId.data.items[0].id>> — array element
459
+ ```
460
+
461
+ ### Execution Pipeline
462
+
463
+ For each step in order:
464
+
465
+ 1. Build `sourceData`: `{ ...originalPayload, ...previousStepResults, ...credentials }`
466
+ 2. Run `dataSelector(sourceData)` → determines single vs loop execution
467
+ 3. For each item: merge `currentItem` into `sourceData`, resolve `<<>>` variables, execute step
468
+ 4. `transformCode` runs on the raw response → output becomes `.data` in the envelope
469
+ 5. Wrap result: `{ currentItem, data, success }` and store in `sourceData[stepId]`
470
+ 6. After all steps: run `outputTransform(sourceData)` to shape final output
471
+
472
+ ### Complete Example: List-then-Detail Pattern
473
+
474
+ A tool that lists Gmail message IDs, then fetches details for each:
475
+
476
+ ```json
477
+ {
478
+ "id": "get-recent-emails",
479
+ "instruction": "Fetches the 10 most recent Gmail emails with subject, sender, and snippet",
480
+ "steps": [
481
+ {
482
+ "id": "list-messages",
483
+ "config": {
484
+ "systemId": "gmail",
485
+ "url": "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10",
486
+ "method": "GET",
487
+ "headers": { "Authorization": "Bearer <<gmail_access_token>>" }
488
+ }
489
+ },
490
+ {
491
+ "id": "get-details",
492
+ "dataSelector": "(sourceData) => sourceData[\"list-messages\"].data.messages.map(m => m.id)",
493
+ "config": {
494
+ "systemId": "gmail",
495
+ "url": "https://gmail.googleapis.com/gmail/v1/users/me/messages/<<currentItem>>?format=metadata&metadataHeaders=Subject&metadataHeaders=From&metadataHeaders=Date",
496
+ "method": "GET",
497
+ "headers": { "Authorization": "Bearer <<gmail_access_token>>" }
498
+ }
499
+ }
500
+ ],
501
+ "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 }; })"
502
+ }
503
+ ```
504
+
505
+ What happens at runtime:
506
+
507
+ 1. **list-messages** runs once (no dataSelector) → `sourceData["list-messages"] = { currentItem: {}, data: { messages: [{id: "abc"}, {id: "def"}, ...] }, success: true }`
508
+ 2. **get-details** dataSelector returns `["abc", "def", ...]` (an array) → step loops over each ID
509
+ 3. Each loop iteration sets `currentItem` to the string ID, which `<<currentItem>>` injects into the URL
510
+ 4. Loop results stored as: `sourceData["get-details"] = [{ currentItem: "abc", data: {id, snippet, payload...}, success }, ...]`
511
+ 5. **outputTransform** maps over the array of envelopes, extracting `.data` fields from each
512
+
513
+ ---
514
+
515
+ ## HTTP API Patterns
516
+
517
+ ### Pagination
518
+
519
+ ```json
520
+ {
521
+ "pagination": {
522
+ "type": "offset|cursor|page",
523
+ "pageSize": 100,
524
+ "cursorPath": "$.nextPageToken",
525
+ "stopCondition": "(response) => !response.hasMore"
526
+ }
527
+ }
528
+ ```
529
+
530
+ | Type | How it works |
531
+ | -------- | ------------------------------------------------------------ |
532
+ | `offset` | Increments `offset` param by `pageSize` each page |
533
+ | `cursor` | Extracts next cursor from `cursorPath`, sends as query param |
534
+ | `page` | Increments `page` query param |
535
+
536
+ All types stop when `stopCondition` returns true, response is empty, or max pages reached.
537
+
538
+ ### Common Auth Patterns by Service Type
539
+
540
+ | Service | Header |
541
+ | ---------------------------- | ----------------------------------------------------- |
542
+ | OAuth (Google, GitHub, etc.) | `"Authorization": "Bearer <<systemId_access_token>>"` |
543
+ | API Key (Stripe, etc.) | `"Authorization": "Bearer <<systemId_api_key>>"` |
544
+ | API Key in header | `"X-API-Key": "<<systemId_api_key>>"` |
545
+
546
+ ---
547
+
548
+ ## Systems
549
+
550
+ ### Credential Model
551
+
552
+ - `credentials` — non-sensitive config stored directly (client_id, auth_url, scopes, etc.)
553
+ - `sensitiveCredentials` — secrets requiring secure UI input (api_key, client_secret)
554
+ - **NEVER ask users to paste secrets in chat** — always use `--sensitive-credentials`
555
+
556
+ ### Templates
557
+
558
+ Templates auto-populate endpoints and OAuth config. Use `sg system find` to discover available templates.
559
+
560
+ **Preconfigured OAuth** (no user client_id/secret needed): slack, salesforce, asana, notion, airtable, jira, confluence
561
+
562
+ ### OAuth Flow
563
+
564
+ 1. `sg system create --id gmail --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
565
+ 2. `sg system oauth --system-id gmail --scopes "..."`
566
+ 3. User authenticates in browser → tokens saved automatically
567
+
568
+ ### System IDs
569
+
570
+ - Lowercase letters, numbers, underscores only — **no hyphens**
571
+ - Used for credential namespacing: `<<systemId_credKey>>`
572
+
573
+ ---
574
+
575
+ ## Debugging Failed Tools
576
+
577
+ ### Common Errors and Fixes
578
+
579
+ | Error | Cause | Fix |
580
+ | --------------------- | ---------------------------------- | ------------------------------------------------------------------------- |
581
+ | 401 Unauthorized | Missing or invalid auth header | Add `"Authorization": "Bearer <<systemId_access_token>>"` to step headers |
582
+ | 403 Forbidden | Wrong scopes or permissions | Check OAuth scopes, re-authenticate |
583
+ | Empty `data: {}` | No outputTransform or dataSelector | Add `outputTransform` to extract from step results |
584
+ | Variable not resolved | Wrong placeholder syntax | Check `<<systemId_credKey>>` matches actual credential keys |
585
+ | Step references empty | Wrong step ID in reference | Verify `<<stepId.data.field>>` matches actual step IDs |
586
+
587
+ ### Debug Workflow
588
+
589
+ 1. Run with `--include-step-results` to see raw step responses
590
+ 2. Check each step's `data` field — is the API returning what you expect?
591
+ 3. Verify credential placeholders match `sg system find --id <systemId>` placeholder list
592
+ 4. **Test API calls directly with `sg system call`** — isolate whether the issue is auth, endpoint, or transform:
593
+ ```bash
594
+ # Test the exact URL from your failing step
595
+ sg system call --url "https://api.example.com/endpoint" \
596
+ --system-id my_api \
597
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
598
+ ```
599
+ 5. Compare `sg system call` response to what your tool expects — fix transforms accordingly
600
+
601
+ ### Self-Healing Pattern
602
+
603
+ When an outputTransform or dataSelector fails, the executor retries with an LLM-generated fix. To help this:
604
+
605
+ - Throw descriptive errors: `throw new Error("Expected array at data.items, got: " + typeof data.items)`
606
+ - Check for null/undefined with `?.` and defaults
607
+ - Validate arrays with `Array.isArray()` before calling array methods
608
+
609
+ ---
610
+
611
+ ## Workflow Guide
612
+
613
+ ### Pre-Building: Test with `sg system call`
614
+
615
+ **ALWAYS test endpoints with `sg system call` before building tools.** This is the most important step to avoid broken tools.
616
+
617
+ 1. **Verify authentication** — Test that credentials work:
618
+
619
+ ```bash
620
+ sg system call --url "https://api.example.com/me" \
621
+ --system-id my_api \
622
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
623
+ ```
624
+
625
+ 2. **Explore response structure** — Understand what the API returns:
626
+
627
+ ```bash
628
+ sg system call --url "https://api.example.com/users?limit=2" \
629
+ --system-id my_api \
630
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
631
+ ```
632
+
633
+ Look at the response to understand:
634
+ - Where is the data array? (`data.users`, `data.items`, `data.results`?)
635
+ - What fields are available? (exact field names matter!)
636
+ - Is there pagination info? (`nextCursor`, `hasMore`, `total`?)
637
+
638
+ 3. **Test the exact endpoints your tool will use** — Don't guess:
639
+ ```bash
640
+ # If your tool will fetch user details by ID:
641
+ sg system call --url "https://api.example.com/users/123" \
642
+ --system-id my_api \
643
+ --headers '{"Authorization":"Bearer <<my_api_access_token>>"}'
644
+ ```
645
+
646
+ ### Full Workflow
647
+
648
+ 1. **Create system** → `sg system create --id my_api --url ... --sensitive-credentials api_key`
649
+ 2. **Authenticate** → `sg system oauth` (if OAuth) or credentials are already set
650
+ 3. **Test auth** → `sg system call` to verify credentials work
651
+ 4. **Explore API** → `sg system search-docs` + more `sg system call` to test endpoints
652
+ 5. **Build tool** → Construct full config JSON, `sg tool build --config '...'`
653
+ 6. **Test** → `sg tool run --draft <id> --include-step-results`
654
+ 7. **Iterate** → `sg tool edit --draft <id> --patches '[...]' --test`
655
+ 8. **Save** → `sg tool save --draft <id>`
656
+
657
+ ---
658
+
659
+ ## Deploying Tools to Production
660
+
661
+ After building and saving a tool, integrate it into your application:
662
+
663
+ ### REST API (Any Language)
664
+
665
+ ```bash
666
+ # Run a tool
667
+ curl -X POST "https://api.superglue.cloud/v1/tools/{toolId}/run" \
668
+ -H "Authorization: Bearer $SUPERGLUE_API_KEY" \
669
+ -H "Content-Type: application/json" \
670
+ -d '{"inputs": {"userId": "123"}}'
671
+
672
+ # Webhook trigger (async, fire-and-forget)
673
+ curl -X POST "https://api.superglue.cloud/v1/hooks/{toolId}?token=$SUPERGLUE_API_KEY" \
674
+ -H "Content-Type: application/json" \
675
+ -d '{"userId": "123"}'
676
+ ```
677
+
678
+ ### TypeScript SDK
679
+
680
+ ```typescript
681
+ import { configure, runTool } from "@superglue/client";
682
+ configure({ apiKey: process.env.SUPERGLUE_API_KEY });
683
+ const { data } = await runTool("my-tool-id", { inputs: { userId: "123" } });
684
+ ```
685
+
686
+ ### Python SDK
687
+
688
+ ```python
689
+ import os
690
+ from superglue_client import SuperglueClient
691
+ from superglue_client.api.tools import run_tool
692
+ client = SuperglueClient(base_url="https://api.superglue.cloud/v1", token=os.environ["SUPERGLUE_API_KEY"])
693
+ result = run_tool.sync(client=client, tool_id="my-tool-id", body={"inputs": {"userId": "123"}})
694
+ ```
695
+
696
+ **For complete integration patterns** (error handling, retries, webhooks, async execution), read `references/integration.md`.
697
+
698
+ ---
699
+
700
+ ## Reference Files
701
+
702
+ For detailed documentation on specific topics, read these files in the `references/` directory:
703
+
704
+ | File | When to read |
705
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------ |
706
+ | `references/integration.md` | **READ THIS** when deploying tools to production - SDK usage, REST API, webhooks, error handling |
707
+ | `references/databases.md` | Building tools that query PostgreSQL/MySQL databases |
708
+ | `references/file-servers.md` | Building tools that interact with FTP/SFTP/SMB file servers |
709
+ | `references/transforms-and-output.md` | Complex data transformations, output shaping, JS sandbox constraints |
710
+
711
+ **Important:** When the user asks about integrating superglue into their codebase, deploying tools, using the SDK, or calling tools from code, you MUST read `references/integration.md` for complete examples.
712
+
713
+ ---
714
+
715
+ ## Draft Management
716
+
717
+ Drafts live in `.superglue/drafts/<draftId>.json`. Created by `build`, updated by `edit`, deleted by `save`. Ephemeral — not persisted across sessions.
718
+
719
+ ## File References
720
+
721
+ Attach files with `--file key=path`. Reference in payloads with `file::<key>`. Auto-parsed via `/v1/extract`.
722
+
723
+ ```bash
724
+ sg tool run --draft <id> --payload '{"data": "file::mysheet"}' --file mysheet=data.xlsx
725
+ ```
726
+
727
+ ## Configuration
728
+
729
+ Created by `sg init` at `.superglue/config.json` (project-local) or `~/.superglue/config.json` (global):
730
+
731
+ ```json
732
+ {
733
+ "apiKey": "...",
734
+ "endpoint": "https://api.superglue.cloud",
735
+ "webEndpoint": "https://app.superglue.cloud",
736
+ "output": { "mode": "stdout", "directory": ".superglue/output" }
737
+ }
738
+ ```
739
+
740
+ Config file is optional if `SUPERGLUE_API_KEY` and `SUPERGLUE_API_ENDPOINT` env vars are set. See **Installation & Setup** above.