@superglue/cli 1.1.1 → 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.
@@ -7,58 +7,32 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
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:**
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
21
+ **Saving Tools:**
22
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
- ```
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
41
26
 
42
- **Other Critical Rules:**
27
+ **Credentials in Non-Interactive Environments (AI Agents, CI):**
43
28
 
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`
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"}'`
50
31
 
51
32
  ---
52
33
 
53
34
  ## Installation & Setup
54
35
 
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
36
  ### Installing the CLI
63
37
 
64
38
  ```bash
@@ -69,7 +43,7 @@ After installation, the `sg` command is available globally.
69
43
 
70
44
  ### Initialization (REQUIRED before first use)
71
45
 
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.
46
+ The CLI **will not work** until configured with an API key. The endpoint defaults to `https://api.superglue.cloud` if not specified.
73
47
 
74
48
  **Option A: Interactive setup (recommended for humans)**
75
49
 
@@ -116,14 +90,12 @@ After configuring, verify the connection works:
116
90
  sg system list # should return a list (possibly empty) without errors
117
91
  ```
118
92
 
119
- If you see `fetch failed`, `ECONNREFUSED`, or authentication errors, double-check your API key and endpoint.
120
-
121
93
  ---
122
94
 
123
95
  ## Quick Start
124
96
 
125
97
  ```bash
126
- sg system list # verify connection
98
+ sg system list
127
99
  sg tool build --config '{"id":"...","instruction":"...","steps":[...]}'
128
100
  sg tool run --draft <draftId>
129
101
  sg tool save --draft <draftId>
@@ -137,8 +109,6 @@ sg tool save --draft <draftId>
137
109
  | `--api-key <key>` | Override API key |
138
110
  | `--endpoint <url>` | Override API endpoint |
139
111
 
140
- ---
141
-
142
112
  ## Command Reference
143
113
 
144
114
  ### `sg init`
@@ -150,17 +120,17 @@ Interactive setup — API key, endpoint, output mode. Creates `.superglue/`.
150
120
  **`sg tool build`** — Register a tool config. Returns a `draftId`. Not AI-powered — you provide the full config.
151
121
 
152
122
  ```bash
153
- sg tool build --config tool.json # from file
154
123
  sg tool build --config '{"id":"...","steps":[...]}' # inline JSON
155
124
  sg tool build --id my-tool --instruction "..." --steps steps.json --payload '{"key":"val"}'
125
+ sg tool build --config tool.json # from file
156
126
  ```
157
127
 
158
128
  | `--config <file-or-json>` | Full JSON config (file path or inline JSON string) |
159
129
  | `--id <id>` | Tool ID (kebab-case) |
160
130
  | `--instruction <text>` | Human-readable description |
161
131
  | `--steps <file>` | JSON file with steps array |
162
- | `--payload <json>` | Sample payload (generates inputSchema) |
163
- | `--file <key=path>` | Attach file reference (repeatable) |
132
+ | `--payload <json>` | Sample payload |
133
+ | `--file <key=path>` | Attach file reference |
164
134
 
165
135
  **`sg tool run`** — Execute a draft or saved tool. Streams live execution logs to the terminal.
166
136
 
@@ -178,11 +148,10 @@ sg tool run --tool my-tool --payload-file payload.json
178
148
 
179
149
  ```bash
180
150
  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 '{...}'
151
+ sg tool edit --tool my-tool --patches patches.json
182
152
  ```
183
153
 
184
154
  | `--patches <json-or-file>` | JSON Patch array (inline or file) |
185
- | `--test` | Run patched tool after accepting |
186
155
 
187
156
  **`sg tool save`** — Persist draft to database. Deletes draft file on success.
188
157
 
@@ -202,34 +171,53 @@ sg tool find --id my-tool # exact ID lookup (full config)
202
171
 
203
172
  **`sg system create`**
204
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
+
187
+ ```bash
188
+ sg system create --id my_api --name "My API" --url https://api.example.com \
189
+ --credentials '{"api_key":"sk-xxx"}'
190
+ ```
191
+
192
+ **With template:**
193
+
205
194
  ```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
195
+ sg system create --id slack --name "Slack" --template slack
208
196
  ```
209
197
 
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) |
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) |
217
211
 
218
212
  **`sg system edit`** — Update system config or credentials. Supports `--env dev|prod`.
219
213
  **`sg system list` / `sg system find`** — List or search systems. `find` supports `--env dev|prod`.
220
214
 
221
215
  **`sg system call`** — **CRITICAL for tool building.** Make authenticated calls to APIs, databases, and file servers. Use this to:
222
216
 
223
- - Test system authentication works
224
217
  - Explore API endpoints and response structures
225
218
  - Verify field names and data shapes BEFORE building tools
226
- - Debug failing tools by testing individual endpoints
227
219
 
228
220
  ```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
221
 
234
222
  # POST request with auth and body
235
223
  sg system call --url https://api.example.com/users \
@@ -303,8 +291,7 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
303
291
  "body": "{ \"key\": \"<<payload_field>>\" }"
304
292
  },
305
293
  "dataSelector": "(sourceData) => sourceData.previousStep.data.items",
306
- "transformCode": "(items) => items.map(i => ({ id: i.id, name: i.name }))",
307
- "failureBehavior": "abort"
294
+ "failureBehavior": "fail"
308
295
  }
309
296
  ],
310
297
  "outputTransform": "(sourceData) => sourceData.stepId.data",
@@ -313,10 +300,11 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
313
300
  }
314
301
  ```
315
302
 
316
- ### Step Config Fields
303
+ ### Step Config Fields (Request Steps)
317
304
 
318
305
  | Field | Type | Description |
319
306
  | ------------- | ------ | -------------------------------------------- |
307
+ | `type` | string | `"request"` (default, can be omitted) |
320
308
  | `systemId` | string | System whose credentials to use |
321
309
  | `url` | string | Full URL with `<<variable>>` placeholders |
322
310
  | `method` | string | HTTP method |
@@ -325,13 +313,19 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
325
313
  | `body` | string | Request body (JSON string with placeholders) |
326
314
  | `pagination` | object | Auto-pagination config (see below) |
327
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
+
328
323
  ### Step Behavior Fields
329
324
 
330
325
  | Field | Type | Description |
331
326
  | ----------------- | ------ | ------------------------------------------------ |
332
327
  | `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` |
328
+ | `failureBehavior` | string | `fail` (default) or `continue` |
335
329
 
336
330
  ---
337
331
 
@@ -345,15 +339,16 @@ System credentials are namespaced as `<<systemId_credentialKey>>` and resolved s
345
339
  {"Authorization": "Bearer <<stripe_api_key>>"}
346
340
  {"Authorization": "Bearer <<gmail_access_token>>"}
347
341
  {"X-API-Key": "<<my_api_api_key>>"}
348
- {"Authorization": "Basic <<(sourceData) => Buffer.from(sourceData.my_api_username + ':' + sourceData.my_api_password).toString('base64')>>"}
342
+ {"Authorization": "Basic <<my_api_username>>:<<my_api_password>>"}
349
343
  ```
350
344
 
345
+ Basic auth is auto-encoded: if the value after `Basic ` isn't already base64, the engine encodes it automatically.
346
+
351
347
  ### Credential Lifecycle
352
348
 
353
349
  - 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
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.
355
351
  - 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
352
 
358
353
  ---
359
354
 
@@ -367,7 +362,6 @@ All step config fields support `<<variable>>` placeholders:
367
362
  | -------------------------- | --------------------------- |
368
363
  | `<<fieldName>>` | Payload field or credential |
369
364
  | `<<systemId_credKey>>` | System credential |
370
- | `<<stepId.data.field>>` | Previous step result |
371
365
  | `<<(sourceData) => expr>>` | JavaScript expression |
372
366
 
373
367
  **CRITICAL**: Simple `<<varName>>` only works for **top-level keys**. No dots, no nesting.
@@ -426,16 +420,8 @@ sourceData.stepId = [
426
420
  { currentItem: <item2>, data: <response2>, success: true },
427
421
  ...
428
422
  ]
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
423
  ```
436
424
 
437
- **NEVER** access step results without `.data` — `sourceData.stepId.results` hits the envelope, not the API response. Use `sourceData.stepId.data.results`.
438
-
439
425
  ### Data Selectors
440
426
 
441
427
  Control what a step receives as input and whether it loops:
@@ -450,14 +436,46 @@ In loop mode, `sourceData.currentItem` is set to the current array element.
450
436
 
451
437
  Empty arrays are valid — the step simply skips execution.
452
438
 
453
- ### Step Result References (in `<<>>` placeholders)
439
+ ### Two Step Types
440
+
441
+ **Request step** (HTTP, Postgres, FTP/SFTP/SMB) — makes an API call:
454
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
+ }
455
454
  ```
456
- <<stepId.data>> — full response data (object-selector step)
457
- <<stepId.data.field>> — nested field
458
- <<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
+ }
459
466
  ```
460
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
+
461
479
  ### Execution Pipeline
462
480
 
463
481
  For each step in order:
@@ -465,50 +483,10 @@ For each step in order:
465
483
  1. Build `sourceData`: `{ ...originalPayload, ...previousStepResults, ...credentials }`
466
484
  2. Run `dataSelector(sourceData)` → determines single vs loop execution
467
485
  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
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
512
490
 
513
491
  ---
514
492
 
@@ -535,23 +513,14 @@ What happens at runtime:
535
513
 
536
514
  All types stop when `stopCondition` returns true, response is empty, or max pages reached.
537
515
 
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
516
  ## Systems
549
517
 
550
518
  ### Credential Model
551
519
 
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`
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
555
524
 
556
525
  ### Templates
557
526
 
@@ -574,85 +543,12 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
574
543
 
575
544
  ## Debugging Failed Tools
576
545
 
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
546
  ### Debug Workflow
588
547
 
589
548
  1. Run with `--include-step-results` to see raw step responses
590
549
  2. Check each step's `data` field — is the API returning what you expect?
591
550
  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>`
551
+ 4. **Test API calls directly with `sg system call`** — isolate whether the issue is auth, endpoint, or transform
656
552
 
657
553
  ---
658
554
 
@@ -679,21 +575,24 @@ curl -X POST "https://api.superglue.cloud/v1/hooks/{toolId}?token=$SUPERGLUE_API
679
575
 
680
576
  ```typescript
681
577
  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" } });
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 }
684
581
  ```
685
582
 
686
583
  ### Python SDK
687
584
 
688
585
  ```python
689
586
  import os
690
- from superglue_client import SuperglueClient
587
+ from superglue_client import AuthenticatedClient
691
588
  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
- ```
589
+ from superglue_client.models.run_request import RunRequest
590
+ from superglue_client.models.run_request_inputs import RunRequestInputs
695
591
 
696
- **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
+ ```
697
596
 
698
597
  ---
699
598
 
@@ -723,18 +622,3 @@ Attach files with `--file key=path`. Reference in payloads with `file::<key>`. A
723
622
  ```bash
724
623
  sg tool run --draft <id> --payload '{"data": "file::mysheet"}' --file mysheet=data.xlsx
725
624
  ```
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.