@withone/cli 1.16.0 → 1.17.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.
- package/dist/{chunk-SX2Y4HDW.js → chunk-QW4MBV4F.js} +6 -4
- package/dist/{flow-runner-7RUK2WMF.js → flow-runner-AJGIUT6E.js} +1 -1
- package/dist/index.js +301 -274
- package/package.json +1 -1
- package/skills/one/SKILL.md +116 -0
- package/skills/one/references/flows.md +278 -0
- package/skills/one/references/relay.md +179 -0
- package/skills/one-actions/SKILL.md +0 -157
- package/skills/one-flow/SKILL.md +0 -917
- package/skills/one-relay/SKILL.md +0 -303
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: one
|
|
3
|
+
description: |
|
|
4
|
+
Use the One CLI (`one`) to interact with 250+ third-party platforms — Gmail, Slack, Shopify, HubSpot, Stripe, GitHub, Notion, Salesforce, and more — through their APIs. One handles authentication, request building, and execution through a single unified interface.
|
|
5
|
+
|
|
6
|
+
TRIGGER when the user wants to:
|
|
7
|
+
- Interact with ANY third-party platform or external service (e.g., "send an email", "create a Shopify order", "look up a HubSpot contact", "post to Slack")
|
|
8
|
+
- List their connected platforms or check what integrations are available
|
|
9
|
+
- Search for what they can do on a platform (e.g., "what can I do with Gmail")
|
|
10
|
+
- Execute any API call against a connected platform
|
|
11
|
+
- Set up webhook-driven automations between platforms (e.g., "when a Stripe payment comes in, notify Slack")
|
|
12
|
+
- Build multi-step workflows that chain actions across platforms (e.g., "fetch Stripe customers and email each one")
|
|
13
|
+
- Anything involving third-party APIs, integrations, or connected apps — even if they don't mention "One" by name
|
|
14
|
+
|
|
15
|
+
DO NOT TRIGGER for:
|
|
16
|
+
- Setting up One or installing MCP (that's `one init`)
|
|
17
|
+
- Adding new connections (that's `one add <platform>`)
|
|
18
|
+
- Configuring access control (that's `one config`)
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# One CLI
|
|
22
|
+
|
|
23
|
+
You have access to the One CLI which lets you interact with 250+ third-party platforms through their APIs. Always include the `--agent` flag right after `one` for structured JSON output.
|
|
24
|
+
|
|
25
|
+
## Core Workflow: search -> knowledge -> execute
|
|
26
|
+
|
|
27
|
+
Always follow this sequence when the user wants to do something on a connected platform:
|
|
28
|
+
|
|
29
|
+
### 1. List connections
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
one --agent connection list
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Returns connected platforms with their connection keys (needed for execution) and platform names in kebab-case (needed for searching).
|
|
36
|
+
|
|
37
|
+
### 2. Search for the right action
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
one --agent actions search <platform> "<query>" -t execute
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Platform names are always kebab-case: `gmail`, `hub-spot`, `ship-station`
|
|
44
|
+
- Use `-t execute` when performing actions, `-t knowledge` when researching or writing code
|
|
45
|
+
- If no results, broaden the query (e.g., `"list"` instead of `"list active premium customers"`)
|
|
46
|
+
|
|
47
|
+
### 3. Get the action's knowledge (REQUIRED before executing)
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
one --agent actions knowledge <platform> <actionId>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This tells you exactly what parameters are required, how to structure the request, and which flags to use. Never skip this step — without it you'll guess wrong on parameters.
|
|
54
|
+
|
|
55
|
+
### 4. Execute
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
one --agent actions execute <platform> <actionId> <connectionKey> [options]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Options:
|
|
62
|
+
- `-d, --data <json>` — Request body (POST, PUT, PATCH)
|
|
63
|
+
- `--path-vars <json>` — Path variables for URLs with `{id}` placeholders
|
|
64
|
+
- `--query-params <json>` — Query parameters
|
|
65
|
+
- `--headers <json>` — Additional headers
|
|
66
|
+
- `--form-data` — Send as multipart/form-data
|
|
67
|
+
- `--form-url-encoded` — Send as application/x-www-form-urlencoded
|
|
68
|
+
- `--dry-run` — Preview the request without executing
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
```bash
|
|
72
|
+
# Simple GET
|
|
73
|
+
one --agent actions execute shopify <actionId> <connectionKey>
|
|
74
|
+
|
|
75
|
+
# POST with body data
|
|
76
|
+
one --agent actions execute hub-spot <actionId> <connectionKey> \
|
|
77
|
+
-d '{"properties": {"email": "jane@example.com", "firstname": "Jane"}}'
|
|
78
|
+
|
|
79
|
+
# Path variables + query params
|
|
80
|
+
one --agent actions execute shopify <actionId> <connectionKey> \
|
|
81
|
+
--path-vars '{"order_id": "12345"}' \
|
|
82
|
+
--query-params '{"limit": "10"}'
|
|
83
|
+
|
|
84
|
+
# Array query params (expand to repeated keys)
|
|
85
|
+
one --agent actions execute gmail <actionId> <connectionKey> \
|
|
86
|
+
--path-vars '{"userId": "me", "id": "msg123"}' \
|
|
87
|
+
--query-params '{"format": "metadata", "metadataHeaders": ["From", "Subject", "Date"]}'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Error Handling
|
|
91
|
+
|
|
92
|
+
All errors return JSON: `{"error": "message"}`. Parse output as JSON and check for the `error` key.
|
|
93
|
+
|
|
94
|
+
## Important Rules
|
|
95
|
+
|
|
96
|
+
- Always use `--agent` flag for structured JSON output
|
|
97
|
+
- Platform names are always kebab-case (`hub-spot` not `HubSpot`)
|
|
98
|
+
- Always use the exact action ID from search results — never guess or construct them
|
|
99
|
+
- Always read knowledge before executing — it has required params, validation rules, and caveats
|
|
100
|
+
- JSON values passed to `-d`, `--path-vars`, `--query-params` must be valid JSON (use single quotes around JSON to avoid shell escaping)
|
|
101
|
+
- Do NOT pass path or query parameters inside the `-d` body flag
|
|
102
|
+
|
|
103
|
+
## Beyond Single Actions
|
|
104
|
+
|
|
105
|
+
One also supports more advanced patterns. Read the relevant reference file before using these:
|
|
106
|
+
|
|
107
|
+
- **Webhook Relay** — Receive webhooks from a platform and forward to another (e.g., Stripe event -> Slack message). Read `references/relay.md` in this skill's directory for the full workflow.
|
|
108
|
+
- **Multi-step Workflows** — Chain actions across platforms as JSON workflow files (like n8n/Zapier but file-based). Read `references/flows.md` in this skill's directory for the schema and examples.
|
|
109
|
+
|
|
110
|
+
## Adding New Connections
|
|
111
|
+
|
|
112
|
+
If the user needs a platform that isn't connected yet, tell them to run:
|
|
113
|
+
```bash
|
|
114
|
+
one add <platform>
|
|
115
|
+
```
|
|
116
|
+
This is interactive and opens the browser for OAuth. After connecting, the platform will appear in `one --agent connection list`.
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# One Workflows — Multi-Step API Workflows
|
|
2
|
+
|
|
3
|
+
Workflows chain actions across platforms as JSON files stored at `.one/flows/<key>.flow.json`. Like n8n/Zapier but file-based.
|
|
4
|
+
|
|
5
|
+
## Building a Workflow
|
|
6
|
+
|
|
7
|
+
### Step 0: Design first
|
|
8
|
+
|
|
9
|
+
Before touching CLI commands:
|
|
10
|
+
1. Clarify the end goal — what output does the user need?
|
|
11
|
+
2. Map every step required to deliver that output
|
|
12
|
+
3. Identify where AI analysis is needed (summarization, scoring, classification)
|
|
13
|
+
4. Write the step sequence as a plain list before constructing JSON
|
|
14
|
+
|
|
15
|
+
Common mistake: jumping straight to `actions search` and building a raw data pipe. Design first.
|
|
16
|
+
|
|
17
|
+
### Step 1: Discover connections
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
one --agent connection list
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Step 2: Get knowledge for EACH action
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
one --agent actions search <platform> "<query>" -t execute
|
|
27
|
+
one --agent actions knowledge <platform> <actionId>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
You MUST call knowledge for every action in the workflow — it tells you the exact body structure, required fields, and path variables.
|
|
31
|
+
|
|
32
|
+
### Step 3: Build the workflow JSON
|
|
33
|
+
|
|
34
|
+
### Step 4: Create
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
one --agent flow create <key> --definition '<json>'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or write directly to `.one/flows/<key>.flow.json`.
|
|
41
|
+
|
|
42
|
+
### Step 5: Validate
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
one --agent flow validate <key>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Step 6: Execute
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
one --agent flow execute <key> -i connectionKey=xxx -i param=value
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Workflow JSON Schema
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"key": "welcome-customer",
|
|
59
|
+
"name": "Welcome New Customer",
|
|
60
|
+
"description": "Look up Stripe customer, send welcome email",
|
|
61
|
+
"version": "1",
|
|
62
|
+
"inputs": {
|
|
63
|
+
"stripeConnectionKey": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"required": true,
|
|
66
|
+
"description": "Stripe connection key",
|
|
67
|
+
"connection": { "platform": "stripe" }
|
|
68
|
+
},
|
|
69
|
+
"customerEmail": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"required": true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"steps": [...]
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Input Fields
|
|
79
|
+
|
|
80
|
+
| Field | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `type` | `string`, `number`, `boolean`, `object`, `array` |
|
|
83
|
+
| `required` | Whether input must be provided (default: true) |
|
|
84
|
+
| `default` | Default value if not provided |
|
|
85
|
+
| `description` | Human-readable description |
|
|
86
|
+
| `connection` | `{ "platform": "gmail" }` — enables auto-resolution |
|
|
87
|
+
|
|
88
|
+
Connection inputs with a `connection` field auto-resolve if the user has exactly one connection for that platform.
|
|
89
|
+
|
|
90
|
+
## Selector Syntax
|
|
91
|
+
|
|
92
|
+
| Pattern | Resolves To |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `$.input.connectionKey` | Input value |
|
|
95
|
+
| `$.steps.stepId.response` | Full API response from a step |
|
|
96
|
+
| `$.steps.stepId.response.data[0].email` | Nested field with array index |
|
|
97
|
+
| `$.steps.stepId.response.data[*].id` | Wildcard — maps array to field |
|
|
98
|
+
| `$.env.MY_VAR` | Environment variable |
|
|
99
|
+
| `$.loop.item` | Current loop item |
|
|
100
|
+
| `$.loop.i` | Current loop index |
|
|
101
|
+
| `"Hello {{$.steps.getUser.response.data.name}}"` | String interpolation |
|
|
102
|
+
|
|
103
|
+
A pure `$.xxx` value resolves to the raw type. A string containing `{{$.xxx}}` does string interpolation.
|
|
104
|
+
|
|
105
|
+
## Step Types
|
|
106
|
+
|
|
107
|
+
### `action` — Execute a One API action
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"id": "findCustomer",
|
|
112
|
+
"type": "action",
|
|
113
|
+
"action": {
|
|
114
|
+
"platform": "stripe",
|
|
115
|
+
"actionId": "conn_mod_def::xxx::yyy",
|
|
116
|
+
"connectionKey": "$.input.stripeConnectionKey",
|
|
117
|
+
"data": { "query": "email:'{{$.input.customerEmail}}'" }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `transform` — JS expression (implicit return)
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"id": "extractNames",
|
|
127
|
+
"type": "transform",
|
|
128
|
+
"transform": { "expression": "$.steps.findCustomer.response.data.map(c => c.name)" }
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### `code` — Multi-line JS (explicit return, async, supports await)
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"id": "processData",
|
|
137
|
+
"type": "code",
|
|
138
|
+
"code": {
|
|
139
|
+
"source": "const customers = $.steps.list.response.data;\nreturn customers.map(c => ({...c, tier: c.spend > 1000 ? 'gold' : 'silver'}));"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### `condition` — If/then/else branching
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"id": "checkFound",
|
|
149
|
+
"type": "condition",
|
|
150
|
+
"condition": {
|
|
151
|
+
"expression": "$.steps.find.response.data.length > 0",
|
|
152
|
+
"then": [{ "id": "sendEmail", "type": "action", "action": {...} }],
|
|
153
|
+
"else": [{ "id": "logNotFound", "type": "transform", "transform": { "expression": "'Not found'" } }]
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `loop` — Iterate over an array
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"id": "processOrders",
|
|
163
|
+
"type": "loop",
|
|
164
|
+
"loop": {
|
|
165
|
+
"over": "$.steps.listOrders.response.orders",
|
|
166
|
+
"as": "order",
|
|
167
|
+
"maxConcurrency": 5,
|
|
168
|
+
"steps": [...]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `parallel` — Run steps concurrently
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"id": "lookups",
|
|
178
|
+
"type": "parallel",
|
|
179
|
+
"parallel": { "maxConcurrency": 5, "steps": [...] }
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### `file-read` / `file-write` — Filesystem access
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{ "id": "read", "type": "file-read", "fileRead": { "path": "./data/config.json", "parseJson": true } }
|
|
187
|
+
{ "id": "write", "type": "file-write", "fileWrite": { "path": "./output/results.json", "content": "$.steps.transform.output" } }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `while` — Condition-driven loop (do-while)
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"id": "paginate",
|
|
195
|
+
"type": "while",
|
|
196
|
+
"while": {
|
|
197
|
+
"condition": "$.steps.paginate.output.lastResult.nextPageToken != null",
|
|
198
|
+
"maxIterations": 50,
|
|
199
|
+
"steps": [...]
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### `flow` — Execute a sub-flow
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"id": "enrich",
|
|
209
|
+
"type": "flow",
|
|
210
|
+
"flow": { "key": "enrich-customer", "inputs": { "email": "$.steps.get.response.email" } }
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### `paginate` — Auto-collect paginated results
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"id": "allMessages",
|
|
219
|
+
"type": "paginate",
|
|
220
|
+
"paginate": {
|
|
221
|
+
"action": { "platform": "gmail", "actionId": "...", "connectionKey": "$.input.gmailKey" },
|
|
222
|
+
"pageTokenField": "nextPageToken",
|
|
223
|
+
"resultsField": "messages",
|
|
224
|
+
"inputTokenParam": "queryParams.pageToken",
|
|
225
|
+
"maxPages": 10
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `bash` — Shell commands (requires `--allow-bash`)
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"id": "analyze",
|
|
235
|
+
"type": "bash",
|
|
236
|
+
"bash": { "command": "cat /tmp/data.json | claude --print 'Analyze this' --output-format json", "timeout": 180000, "parseJson": true }
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Error Handling
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{ "onError": { "strategy": "retry", "retries": 3, "retryDelayMs": 1000 } }
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Strategies: `fail` (default), `continue`, `retry`, `fallback`.
|
|
247
|
+
|
|
248
|
+
Conditional execution: `"if": "$.steps.find.response.data.length > 0"`
|
|
249
|
+
|
|
250
|
+
## AI-Augmented Pattern: file-write -> bash -> code
|
|
251
|
+
|
|
252
|
+
When raw data needs analysis, use this pattern:
|
|
253
|
+
1. `file-write` — save data to temp file (API responses are too large to inline)
|
|
254
|
+
2. `bash` — call `claude --print` to analyze (set timeout to 180000+, use `--output-format json`)
|
|
255
|
+
3. `code` — parse and structure the AI output for downstream steps
|
|
256
|
+
|
|
257
|
+
## CLI Commands
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
one --agent flow create <key> --definition '<json>'
|
|
261
|
+
one --agent flow list
|
|
262
|
+
one --agent flow validate <key>
|
|
263
|
+
one --agent flow execute <key> -i key=value
|
|
264
|
+
one --agent flow execute <key> --dry-run -i key=value
|
|
265
|
+
one --agent flow execute <key> --dry-run --mock -i key=value
|
|
266
|
+
one --agent flow execute <key> --allow-bash -i key=value
|
|
267
|
+
one --agent flow runs [flowKey]
|
|
268
|
+
one --agent flow resume <runId>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Important Notes
|
|
272
|
+
|
|
273
|
+
- Connection keys are inputs, not hardcoded — makes workflows portable
|
|
274
|
+
- Action IDs in examples are placeholders — always use `actions search` to find real IDs
|
|
275
|
+
- Code steps support `require('crypto')`, `require('buffer')`, `require('url')`, `require('path')` — `fs`, `http`, `child_process` are blocked
|
|
276
|
+
- Bash steps require `--allow-bash` flag
|
|
277
|
+
- State is persisted after every step — resume picks up where it left off
|
|
278
|
+
- For bash+Claude steps, always set timeout to 180000+ and run sequentially (not in parallel)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# One Webhook Relay
|
|
2
|
+
|
|
3
|
+
Webhook relay receives webhooks from a source platform and forwards the event data to a destination platform using passthrough actions with Handlebars templates — no middleware, no code needed.
|
|
4
|
+
|
|
5
|
+
## Supported Source Platforms
|
|
6
|
+
|
|
7
|
+
Only these platforms can send webhooks: **Airtable**, **Attio**, **GitHub**, **Google Calendar**, **Stripe**. Any connected platform can be a destination.
|
|
8
|
+
|
|
9
|
+
## Workflow
|
|
10
|
+
|
|
11
|
+
### Step 1: Discover connections
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
one --agent connection list
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Identify source (sends webhooks) and destination (receives forwarded data). Note both connection keys.
|
|
18
|
+
|
|
19
|
+
### Step 2: Get event types
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
one --agent relay event-types <source-platform>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Step 3: Get source knowledge (understand the incoming payload)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
one --agent actions search <source-platform> "<event description>" -t knowledge
|
|
29
|
+
one --agent actions knowledge <source-platform> <actionId>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The knowledge tells you the webhook payload structure — these fields become `{{payload.*}}` in your templates.
|
|
33
|
+
|
|
34
|
+
### Step 4: Get destination knowledge (understand the outgoing API)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
one --agent actions search <dest-platform> "<what you want to do>" -t execute
|
|
38
|
+
one --agent actions knowledge <dest-platform> <actionId>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The knowledge tells you required body fields — these become the keys in your passthrough action's `body`.
|
|
42
|
+
|
|
43
|
+
### Step 5: Create the relay endpoint
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
one --agent relay create \
|
|
47
|
+
--connection-key <source-connection-key> \
|
|
48
|
+
--description "Forward <event> from <source> to <dest>" \
|
|
49
|
+
--event-filters '["event.type"]' \
|
|
50
|
+
--create-webhook
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Always use `--create-webhook` — it registers the webhook URL with the source platform automatically.
|
|
54
|
+
|
|
55
|
+
### Step 6: Activate with a passthrough action
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
one --agent relay activate <relay-id> --actions '[{
|
|
59
|
+
"type": "passthrough",
|
|
60
|
+
"actionId": "<destination-action-id>",
|
|
61
|
+
"connectionKey": "<destination-connection-key>",
|
|
62
|
+
"body": {
|
|
63
|
+
"field": "{{payload.path.to.value}}"
|
|
64
|
+
},
|
|
65
|
+
"eventFilters": ["event.type"]
|
|
66
|
+
}]'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Template Context
|
|
70
|
+
|
|
71
|
+
| Variable | Description |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `{{relayEventId}}` | Unique relay event ID |
|
|
74
|
+
| `{{platform}}` | Source platform name |
|
|
75
|
+
| `{{eventType}}` | Webhook event type |
|
|
76
|
+
| `{{payload}}` | Full incoming webhook body |
|
|
77
|
+
| `{{timestamp}}` | When event was received |
|
|
78
|
+
| `{{connectionId}}` | Source connection UUID |
|
|
79
|
+
|
|
80
|
+
Access nested fields with dot notation: `{{payload.data.object.email}}`
|
|
81
|
+
|
|
82
|
+
Use `{{json payload}}` to embed a full object as a JSON string.
|
|
83
|
+
|
|
84
|
+
## Action Types
|
|
85
|
+
|
|
86
|
+
### `passthrough` — Forward to another platform's API (primary)
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"type": "passthrough",
|
|
91
|
+
"actionId": "<action-id>",
|
|
92
|
+
"connectionKey": "<dest-connection-key>",
|
|
93
|
+
"body": { "channel": "#alerts", "text": "New: {{payload.data.object.name}}" },
|
|
94
|
+
"eventFilters": ["customer.created"]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The `body`, `headers`, and `query` fields all support Handlebars templates.
|
|
99
|
+
|
|
100
|
+
### `url` — Forward raw event to a URL
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"type": "url",
|
|
105
|
+
"url": "https://your-app.com/webhooks/handler",
|
|
106
|
+
"secret": "optional-signing-secret",
|
|
107
|
+
"eventFilters": ["customer.created"]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `agent` — Send to an agent
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"type": "agent",
|
|
116
|
+
"agentId": "<agent-uuid>",
|
|
117
|
+
"eventFilters": ["customer.created"]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Complete Example: Stripe customer.created -> Slack message
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# 1. Get connections
|
|
125
|
+
one --agent connection list
|
|
126
|
+
# stripe: live::stripe::default::abc123, slack: live::slack::default::xyz789
|
|
127
|
+
|
|
128
|
+
# 2. Get event types
|
|
129
|
+
one --agent relay event-types stripe
|
|
130
|
+
|
|
131
|
+
# 3. Get Slack send message action
|
|
132
|
+
one --agent actions search slack "send message" -t execute
|
|
133
|
+
one --agent actions knowledge slack <actionId>
|
|
134
|
+
|
|
135
|
+
# 4. Create relay
|
|
136
|
+
one --agent relay create \
|
|
137
|
+
--connection-key "live::stripe::default::abc123" \
|
|
138
|
+
--description "Notify Slack on new Stripe customers" \
|
|
139
|
+
--event-filters '["customer.created"]' \
|
|
140
|
+
--create-webhook
|
|
141
|
+
|
|
142
|
+
# 5. Activate
|
|
143
|
+
one --agent relay activate <relay-id> --actions '[{
|
|
144
|
+
"type": "passthrough",
|
|
145
|
+
"actionId": "<slack-send-message-action-id>",
|
|
146
|
+
"connectionKey": "live::slack::default::xyz789",
|
|
147
|
+
"body": {
|
|
148
|
+
"channel": "#alerts",
|
|
149
|
+
"text": "New Stripe customer: {{payload.data.object.name}} ({{payload.data.object.email}})"
|
|
150
|
+
},
|
|
151
|
+
"eventFilters": ["customer.created"]
|
|
152
|
+
}]'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Management Commands
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
one --agent relay list [--limit <n>] [--page <n>]
|
|
159
|
+
one --agent relay get <id>
|
|
160
|
+
one --agent relay update <id> [--actions <json>] [--description <desc>]
|
|
161
|
+
one --agent relay delete <id>
|
|
162
|
+
one --agent relay events [--platform <p>] [--event-type <t>] [--limit <n>]
|
|
163
|
+
one --agent relay event <id>
|
|
164
|
+
one --agent relay deliveries --endpoint-id <id>
|
|
165
|
+
one --agent relay deliveries --event-id <id>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Debugging
|
|
169
|
+
|
|
170
|
+
1. Check endpoint is active: `one --agent relay get <id>` — verify `active: true`
|
|
171
|
+
2. Check events arriving: `one --agent relay events --platform <p> --limit 5`
|
|
172
|
+
3. Check delivery status: `one --agent relay deliveries --event-id <id>`
|
|
173
|
+
4. Inspect payload: `one --agent relay event <id>` — verify template paths
|
|
174
|
+
|
|
175
|
+
## Important Notes
|
|
176
|
+
|
|
177
|
+
- Event filters on both the endpoint and individual actions must match
|
|
178
|
+
- Multiple actions can be attached to a single relay endpoint
|
|
179
|
+
- Missing template variables resolve to empty strings — verify `{{payload.*}}` paths against the actual payload
|