@axonflow/n8n-nodes-axonflow 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AxonFlow
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # n8n-nodes-axonflow
2
+
3
+ AxonFlow API integration for [n8n](https://n8n.io). Call the AxonFlow policy and HITL endpoints directly from your n8n workflows.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@axonflow/n8n-nodes-axonflow)](https://www.npmjs.com/package/@axonflow/n8n-nodes-axonflow)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## What it does
9
+
10
+ This package contributes a single `AxonFlow` node with four operations against an AxonFlow Agent:
11
+
12
+ | Operation | Endpoint | When to use |
13
+ |---|---|---|
14
+ | **Check Policy** | `POST /api/v1/mcp/check-input` | Before a workflow takes a sensitive action — receive `{allowed, block_reason?}` and branch on it. |
15
+ | **Record Decision** | `POST /api/v1/audit/tool-call` | After a successful action — capture inputs, outputs, policies applied. |
16
+ | **Audit Log** | `POST /api/v1/audit/tool-call` | From error branches — record the failed action with `success: false` and `error_message`. |
17
+ | **Wait for Approval** | `POST /api/v1/hitl/queue` | When the workflow needs a human in the loop — creates an approval entry and pairs with an n8n Wait node for webhook resume. |
18
+
19
+ Plus a single `AxonFlow API` credential type holding the endpoint + Basic-auth (`clientId` + `userToken`).
20
+
21
+ ## Install
22
+
23
+ ### n8n GUI (self-hosted)
24
+
25
+ 1. **Settings > Community Nodes > Install.**
26
+ 2. npm package name: `@axonflow/n8n-nodes-axonflow`.
27
+ 3. Restart n8n.
28
+
29
+ ### Manual (self-hosted)
30
+
31
+ ```bash
32
+ cd ~/.n8n/custom
33
+ npm install @axonflow/n8n-nodes-axonflow
34
+ # restart n8n
35
+ ```
36
+
37
+ > n8n Cloud does not currently allow unverified community nodes. Use the [stock-HTTP-node recipe](https://docs.getaxonflow.com/docs/integration/n8n/) on n8n Cloud until this package is verified.
38
+
39
+ ## Configure the credential
40
+
41
+ **Credentials > New > AxonFlow API.**
42
+
43
+ | Field | Description |
44
+ |---|---|
45
+ | Endpoint | Base URL of your AxonFlow Agent. SaaS: `https://try.getaxonflow.com`. Self-hosted: typically port 8080. |
46
+ | Client ID | Your tenant identifier. |
47
+ | User Token | Sent as the password half of HTTP Basic auth. Stored encrypted in n8n. |
48
+
49
+ ## Quickstart
50
+
51
+ 1. Install the community node (see above).
52
+ 2. Create an **AxonFlow API** credential with your endpoint + Client ID + User Token.
53
+ 3. Add an **AxonFlow** node to your workflow.
54
+ 4. Pick an operation:
55
+ - **Check Policy** — submit a proposed action and branch on `allowed: true/false`.
56
+ - **Record Decision** — log the outcome of a downstream action.
57
+ - **Audit Log** — log a failed action from an error branch.
58
+ - **Wait for Approval** — create a HITL request and pair with a Wait node for webhook resume.
59
+ 5. Run the workflow.
60
+
61
+ ## Three things to know
62
+
63
+ 1. **Bearer Auth > Header Auth.** This credential uses the Header Auth pattern (Authorization built inline) rather than n8n's built-in Bearer Auth class, which silently drops the header in some n8n versions ([n8n#15261](https://github.com/n8n-io/n8n/issues/15261)).
64
+ 2. **Idempotency by default.** Every operation sends `Idempotency-Key: {executionId}-{itemIndex}-{nodeName}` so n8n's `Retry on Fail` doesn't double-record. Override at the node parameter level if you need a domain-specific key.
65
+ 3. **HITL pairs with the Wait node.** `Wait for Approval` creates the AxonFlow approval entry; pair it with a downstream Wait node configured for **On Webhook Call** mode. As of platform v8.1.0+, pass the Wait node's webhook URL as `notify_url` in the HITL queue request and AxonFlow will POST to it automatically on approval/rejection — no polling sidecar needed. For self-hosted deployments on v8.0.x, two manual paths work: (a) run a small **polling sidecar** that watches `GET /api/v1/hitl/queue/{id}` and POSTs to the Wait node's webhook URL when status changes, or (b) have a reviewer trigger the resume URL manually from the portal. See the [n8n integration docs](https://docs.getaxonflow.com/docs/integration/n8n/#hitl) for details.
66
+
67
+ ## Example workflow
68
+
69
+ [`examples/governed-loan-workflow.json`](./examples/governed-loan-workflow.json) — an importable workflow that:
70
+
71
+ 1. Receives a loan request via HTTP trigger,
72
+ 2. Calls **Check Policy** on the amount,
73
+ 3. If `allowed=false`, branches to **Wait for Approval** (workflow pauses),
74
+ 4. On approval, calls the downstream loan-issuance HTTP endpoint,
75
+ 5. Records the outcome with **Record Decision**, with an error branch to **Audit Log**.
76
+
77
+ Import in n8n: **Workflows > Import from File >** `governed-loan-workflow.json`.
78
+
79
+ ## Build from source
80
+
81
+ ```bash
82
+ git clone https://github.com/getaxonflow/axonflow-n8n-node.git
83
+ cd axonflow-n8n-node
84
+ npm install
85
+ npm run build # tsc > dist/
86
+ npm run lint
87
+ npm test # node --test (25 tests)
88
+ ```
89
+
90
+ ## Documentation
91
+
92
+ - [n8n + AxonFlow Integration Guide](https://docs.getaxonflow.com/docs/integration/n8n/) — full walkthrough including the stock-HTTP-node recipe, HITL polling sidecar, and idempotency details.
93
+ - [AxonFlow](https://getaxonflow.com) — main project site.
94
+ - [AxonFlow on GitHub](https://github.com/getaxonflow/axonflow) — community edition.
95
+
96
+ ## License
97
+
98
+ MIT
@@ -0,0 +1,9 @@
1
+ import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class AxonFlowApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AxonFlowApi = void 0;
4
+ class AxonFlowApi {
5
+ constructor() {
6
+ this.name = 'axonFlowApi';
7
+ this.displayName = 'AxonFlow API';
8
+ this.documentationUrl = 'https://docs.getaxonflow.com/docs/integration/n8n/';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Endpoint',
12
+ name: 'endpoint',
13
+ type: 'string',
14
+ default: 'https://try.getaxonflow.com',
15
+ placeholder: 'https://try.getaxonflow.com',
16
+ description: 'Base URL of your AxonFlow Agent (port 8080 in self-hosted, or your SaaS host).',
17
+ required: true,
18
+ },
19
+ {
20
+ displayName: 'Client ID',
21
+ name: 'clientId',
22
+ type: 'string',
23
+ default: '',
24
+ description: 'AxonFlow client identifier (the tenant your workflow runs under).',
25
+ required: true,
26
+ },
27
+ {
28
+ displayName: 'User Token',
29
+ name: 'userToken',
30
+ type: 'string',
31
+ typeOptions: { password: true },
32
+ default: '',
33
+ description: 'AxonFlow user token. Sent as the password half of HTTP Basic auth.',
34
+ required: true,
35
+ },
36
+ ];
37
+ this.authenticate = {
38
+ type: 'generic',
39
+ properties: {
40
+ headers: {
41
+ Authorization: '=Basic {{ Buffer.from($credentials.clientId + ":" + $credentials.userToken).toString("base64") }}',
42
+ },
43
+ },
44
+ };
45
+ this.test = {
46
+ request: {
47
+ baseURL: '={{ $credentials.endpoint }}',
48
+ url: '/api/v1/mcp/check-input',
49
+ method: 'POST',
50
+ body: {
51
+ client_id: '={{ $credentials.clientId }}',
52
+ user_token: '={{ $credentials.userToken }}',
53
+ tenant_id: '={{ $credentials.clientId }}',
54
+ connector_type: 'credential_test',
55
+ statement: 'n8n_credential_test_noop',
56
+ },
57
+ },
58
+ };
59
+ }
60
+ }
61
+ exports.AxonFlowApi = AxonFlowApi;
62
+ //# sourceMappingURL=AxonFlowApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AxonFlowApi.credentials.js","sourceRoot":"","sources":["../../credentials/AxonFlowApi.credentials.ts"],"names":[],"mappings":";;;AAgBA,MAAa,WAAW;IAAxB;QACC,SAAI,GAAG,aAAa,CAAC;QAErB,gBAAW,GAAG,cAAc,CAAC;QAE7B,qBAAgB,GAAG,oDAAoD,CAAC;QAExE,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,6BAA6B;gBACtC,WAAW,EAAE,6BAA6B;gBAC1C,WAAW,EACV,gFAAgF;gBACjF,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EACV,mEAAmE;gBACpE,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EACV,oEAAoE;gBACrE,QAAQ,EAAE,IAAI;aACd;SACD,CAAC;QAgBF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EACZ,mGAAmG;iBACpG;aACD;SACD,CAAC;QAyBF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,8BAA8B;gBACvC,GAAG,EAAE,yBAAyB;gBAC9B,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACL,SAAS,EAAE,8BAA8B;oBACzC,UAAU,EAAE,+BAA+B;oBAC3C,SAAS,EAAE,8BAA8B;oBACzC,cAAc,EAAE,iBAAiB;oBACjC,SAAS,EAAE,0BAA0B;iBACrC;aACD;SACD,CAAC;IACH,CAAC;CAAA;AApGD,kCAoGC"}
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class AxonFlow implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,435 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AxonFlow = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const DEFAULT_IDEMPOTENCY_TEMPLATE = '={{ $execution.id }}-{{ $itemIndex }}-{{ $node.name }}';
6
+ class AxonFlow {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'AxonFlow',
10
+ name: 'axonFlow',
11
+ icon: 'file:axonflow.svg',
12
+ group: ['transform'],
13
+ version: 1,
14
+ subtitle: '={{ $parameter["operation"] }}',
15
+ description: 'AxonFlow API integration — call policy and HITL endpoints from your workflow.',
16
+ defaults: {
17
+ name: 'AxonFlow',
18
+ },
19
+ inputs: ['main'],
20
+ outputs: ['main'],
21
+ credentials: [
22
+ {
23
+ name: 'axonFlowApi',
24
+ required: true,
25
+ },
26
+ ],
27
+ properties: [
28
+ {
29
+ displayName: 'Operation',
30
+ name: 'operation',
31
+ type: 'options',
32
+ noDataExpression: true,
33
+ options: [
34
+ {
35
+ name: 'Check Policy',
36
+ value: 'checkPolicy',
37
+ description: 'Submit a proposed action to AxonFlow and receive an allow/deny response',
38
+ action: 'Check policy for a proposed action',
39
+ },
40
+ {
41
+ name: 'Record Decision',
42
+ value: 'recordDecision',
43
+ description: 'Record the outcome of a downstream action in AxonFlow',
44
+ action: 'Record a decision',
45
+ },
46
+ {
47
+ name: 'Audit Log',
48
+ value: 'auditLog',
49
+ description: 'Record an event in AxonFlow (typically for error branches)',
50
+ action: 'Record an event',
51
+ },
52
+ {
53
+ name: 'Wait for Approval',
54
+ value: 'waitForApproval',
55
+ description: 'Create a HITL approval request and pause the workflow until a reviewer responds',
56
+ action: 'Wait for HITL approval',
57
+ },
58
+ ],
59
+ default: 'checkPolicy',
60
+ },
61
+ {
62
+ displayName: 'Idempotency Key',
63
+ name: 'idempotencyKey',
64
+ type: 'string',
65
+ default: DEFAULT_IDEMPOTENCY_TEMPLATE,
66
+ description: 'Sent as the Idempotency-Key header. The default is unique per execution-item-node, so n8n retries do not double-record. Override only if you need a domain-specific key.',
67
+ },
68
+ {
69
+ displayName: 'Failure Mode',
70
+ name: 'failureMode',
71
+ type: 'options',
72
+ options: [
73
+ {
74
+ name: 'Open (Continue If AxonFlow Is Unreachable)',
75
+ value: 'open',
76
+ },
77
+ {
78
+ name: 'Closed (Fail If AxonFlow Is Unreachable)',
79
+ value: 'closed',
80
+ },
81
+ ],
82
+ default: 'open',
83
+ description: 'On network errors / 5xx responses from AxonFlow. Open matches the AxonFlow ADK plugin default — the workflow proceeds with a structured fallback payload so the underlying action is not held hostage by an AxonFlow outage. Closed re-throws and stops the workflow; choose this for high-stakes flows where you would rather fail than skip the policy check.',
84
+ },
85
+ {
86
+ displayName: 'Connector Type',
87
+ name: 'connectorType',
88
+ type: 'string',
89
+ default: 'n8n',
90
+ displayOptions: { show: { operation: ['checkPolicy'] } },
91
+ description: 'AxonFlow connector type for this request. Use "n8n" unless you have a custom connector wired up.',
92
+ required: true,
93
+ },
94
+ {
95
+ displayName: 'Statement',
96
+ name: 'statement',
97
+ type: 'string',
98
+ default: '',
99
+ displayOptions: { show: { operation: ['checkPolicy'] } },
100
+ description: 'The proposed action as a string (e.g. SQL, prompt, API verb+path). AxonFlow evaluates this against policies.',
101
+ required: true,
102
+ },
103
+ {
104
+ displayName: 'Operation Type',
105
+ name: 'mcpOperation',
106
+ type: 'options',
107
+ options: [
108
+ { name: 'Execute', value: 'execute' },
109
+ { name: 'Query', value: 'query' },
110
+ ],
111
+ default: 'execute',
112
+ displayOptions: { show: { operation: ['checkPolicy'] } },
113
+ },
114
+ {
115
+ displayName: 'Parameters (JSON)',
116
+ name: 'parameters',
117
+ type: 'json',
118
+ default: '{}',
119
+ displayOptions: { show: { operation: ['checkPolicy'] } },
120
+ description: 'Optional parameters passed alongside the statement',
121
+ },
122
+ {
123
+ displayName: 'Tool Name',
124
+ name: 'toolName',
125
+ type: 'string',
126
+ default: '',
127
+ displayOptions: {
128
+ show: { operation: ['recordDecision', 'auditLog'] },
129
+ },
130
+ description: 'Name of the tool / action being recorded (e.g. "approve_loan")',
131
+ required: true,
132
+ },
133
+ {
134
+ displayName: 'Workflow ID',
135
+ name: 'workflowId',
136
+ type: 'string',
137
+ default: '={{ $workflow.id }}',
138
+ displayOptions: {
139
+ show: { operation: ['recordDecision', 'auditLog'] },
140
+ },
141
+ description: 'Defaults to the running n8n workflow ID so entries are searchable',
142
+ },
143
+ {
144
+ displayName: 'Step ID',
145
+ name: 'stepId',
146
+ type: 'string',
147
+ default: '={{ $node.name }}',
148
+ displayOptions: {
149
+ show: { operation: ['recordDecision', 'auditLog'] },
150
+ },
151
+ },
152
+ {
153
+ displayName: 'Input (JSON)',
154
+ name: 'auditInput',
155
+ type: 'json',
156
+ default: '={{ JSON.stringify($json) }}',
157
+ displayOptions: {
158
+ show: { operation: ['recordDecision', 'auditLog'] },
159
+ },
160
+ description: 'Inputs to record alongside the decision. Defaults to the current item.',
161
+ },
162
+ {
163
+ displayName: 'Output (JSON)',
164
+ name: 'auditOutput',
165
+ type: 'json',
166
+ default: '{}',
167
+ displayOptions: {
168
+ show: { operation: ['recordDecision', 'auditLog'] },
169
+ },
170
+ },
171
+ {
172
+ displayName: 'Success',
173
+ name: 'auditSuccess',
174
+ type: 'boolean',
175
+ default: true,
176
+ displayOptions: {
177
+ show: { operation: ['recordDecision', 'auditLog'] },
178
+ },
179
+ description: 'Whether the recorded action succeeded. Set false from error branches.',
180
+ },
181
+ {
182
+ displayName: 'Error Message',
183
+ name: 'auditErrorMessage',
184
+ type: 'string',
185
+ default: '',
186
+ displayOptions: {
187
+ show: { operation: ['recordDecision', 'auditLog'] },
188
+ },
189
+ },
190
+ {
191
+ displayName: 'Request Type',
192
+ name: 'requestType',
193
+ type: 'string',
194
+ default: 'workflow_step',
195
+ displayOptions: { show: { operation: ['waitForApproval'] } },
196
+ description: 'AxonFlow request_type for the approval entry',
197
+ },
198
+ {
199
+ displayName: 'Original Query / Action',
200
+ name: 'originalQuery',
201
+ type: 'string',
202
+ default: '',
203
+ displayOptions: { show: { operation: ['waitForApproval'] } },
204
+ description: 'Short description of what needs approval',
205
+ required: true,
206
+ },
207
+ {
208
+ displayName: 'Triggered Policy ID',
209
+ name: 'triggeredPolicyId',
210
+ type: 'string',
211
+ default: 'n8n-manual',
212
+ displayOptions: { show: { operation: ['waitForApproval'] } },
213
+ description: 'AxonFlow static_policies.ID that triggered this approval. Use "n8n-manual" for workflow-initiated approvals not tied to a specific policy.',
214
+ },
215
+ {
216
+ displayName: 'Triggered Policy Name',
217
+ name: 'triggeredPolicyName',
218
+ type: 'string',
219
+ default: 'n8n manual approval',
220
+ displayOptions: { show: { operation: ['waitForApproval'] } },
221
+ },
222
+ {
223
+ displayName: 'Trigger Reason',
224
+ name: 'triggerReason',
225
+ type: 'string',
226
+ default: 'Approval requested from n8n workflow',
227
+ displayOptions: { show: { operation: ['waitForApproval'] } },
228
+ },
229
+ {
230
+ displayName: 'Severity',
231
+ name: 'severity',
232
+ type: 'options',
233
+ options: [
234
+ { name: 'Low', value: 'low' },
235
+ { name: 'Medium', value: 'medium' },
236
+ { name: 'High', value: 'high' },
237
+ { name: 'Critical', value: 'critical' },
238
+ ],
239
+ default: 'medium',
240
+ displayOptions: { show: { operation: ['waitForApproval'] } },
241
+ },
242
+ {
243
+ displayName: 'Limit Wait Time (Seconds)',
244
+ name: 'limitWaitTime',
245
+ type: 'number',
246
+ default: 86400,
247
+ displayOptions: { show: { operation: ['waitForApproval'] } },
248
+ description: 'Maps to expires_in_seconds on the AxonFlow approval. Defaults to 24h.',
249
+ },
250
+ {
251
+ displayName: 'Request Context (JSON)',
252
+ name: 'requestContext',
253
+ type: 'json',
254
+ default: '={{ JSON.stringify($json) }}',
255
+ displayOptions: { show: { operation: ['waitForApproval'] } },
256
+ description: 'Arbitrary context surfaced in the AxonFlow portal. Defaults to the current item.',
257
+ },
258
+ ],
259
+ };
260
+ }
261
+ async execute() {
262
+ var _a;
263
+ const items = this.getInputData();
264
+ const credentials = await this.getCredentials('axonFlowApi');
265
+ const endpoint = String(credentials.endpoint || '').replace(/\/+$/, '');
266
+ const clientId = String(credentials.clientId || '');
267
+ const returnData = [];
268
+ for (let i = 0; i < items.length; i++) {
269
+ const operation = this.getNodeParameter('operation', i);
270
+ const idempotencyKey = this.getNodeParameter('idempotencyKey', i, `${this.getExecutionId()}-${i}-${this.getNode().name}`);
271
+ const failureMode = this.getNodeParameter('failureMode', i, 'open');
272
+ try {
273
+ let result;
274
+ switch (operation) {
275
+ case 'checkPolicy':
276
+ result = await this.helpers.httpRequestWithAuthentication.call(this, 'axonFlowApi', buildRequest({
277
+ endpoint,
278
+ method: 'POST',
279
+ path: '/api/v1/mcp/check-input',
280
+ idempotencyKey,
281
+ body: {
282
+ client_id: clientId,
283
+ user_token: String(credentials.userToken || ''),
284
+ tenant_id: clientId,
285
+ connector_type: this.getNodeParameter('connectorType', i),
286
+ statement: this.getNodeParameter('statement', i),
287
+ operation: this.getNodeParameter('mcpOperation', i),
288
+ parameters: parseJsonParam(this.getNodeParameter('parameters', i, '{}')),
289
+ },
290
+ }));
291
+ break;
292
+ case 'recordDecision':
293
+ case 'auditLog':
294
+ result = await this.helpers.httpRequestWithAuthentication.call(this, 'axonFlowApi', buildRequest({
295
+ endpoint,
296
+ method: 'POST',
297
+ path: '/api/v1/audit/tool-call',
298
+ idempotencyKey,
299
+ body: {
300
+ tool_name: this.getNodeParameter('toolName', i),
301
+ tool_type: operation === 'auditLog' ? 'n8n_audit' : 'n8n_decision',
302
+ workflow_id: this.getNodeParameter('workflowId', i),
303
+ step_id: this.getNodeParameter('stepId', i),
304
+ input: parseJsonParam(this.getNodeParameter('auditInput', i, '{}')),
305
+ output: parseJsonParam(this.getNodeParameter('auditOutput', i, '{}')),
306
+ success: this.getNodeParameter('auditSuccess', i),
307
+ error_message: this.getNodeParameter('auditErrorMessage', i, ''),
308
+ },
309
+ }));
310
+ break;
311
+ case 'waitForApproval': {
312
+ const limitWaitTime = this.getNodeParameter('limitWaitTime', i);
313
+ const createResp = (await this.helpers.httpRequestWithAuthentication.call(this, 'axonFlowApi', buildRequest({
314
+ endpoint,
315
+ method: 'POST',
316
+ path: '/api/v1/hitl/queue',
317
+ idempotencyKey,
318
+ body: {
319
+ client_id: clientId,
320
+ original_query: this.getNodeParameter('originalQuery', i),
321
+ request_type: this.getNodeParameter('requestType', i),
322
+ request_context: parseJsonParam(this.getNodeParameter('requestContext', i, '{}')),
323
+ triggered_policy_id: this.getNodeParameter('triggeredPolicyId', i),
324
+ triggered_policy_name: this.getNodeParameter('triggeredPolicyName', i),
325
+ trigger_reason: this.getNodeParameter('triggerReason', i),
326
+ severity: this.getNodeParameter('severity', i),
327
+ expires_in_seconds: limitWaitTime,
328
+ },
329
+ })));
330
+ const approvalData = extractApprovalData(createResp, this.getNode());
331
+ result = {
332
+ approval_id: approvalData.id,
333
+ status: (_a = approvalData.status) !== null && _a !== void 0 ? _a : 'pending',
334
+ expires_at: approvalData.expires_at,
335
+ resume_hint: 'Use notify_url (v8.1.0+) to auto-POST approval events to a Wait node webhook, or poll GET /api/v1/hitl/queue/{id}. See https://docs.getaxonflow.com/docs/integration/n8n/#hitl.',
336
+ raw: createResp,
337
+ };
338
+ break;
339
+ }
340
+ default:
341
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
342
+ }
343
+ returnData.push({
344
+ json: result,
345
+ pairedItem: { item: i },
346
+ });
347
+ }
348
+ catch (error) {
349
+ if (this.continueOnFail()) {
350
+ returnData.push({
351
+ json: { error: error.message },
352
+ pairedItem: { item: i },
353
+ });
354
+ continue;
355
+ }
356
+ if (failureMode === 'open' && shouldFailOpen(error)) {
357
+ returnData.push({
358
+ json: {
359
+ _axonflow_unreachable: true,
360
+ error: error.message,
361
+ operation,
362
+ },
363
+ pairedItem: { item: i },
364
+ });
365
+ continue;
366
+ }
367
+ throw error;
368
+ }
369
+ }
370
+ return [returnData];
371
+ }
372
+ }
373
+ exports.AxonFlow = AxonFlow;
374
+ function buildRequest(args) {
375
+ const headers = {
376
+ 'Content-Type': 'application/json',
377
+ Accept: 'application/json',
378
+ };
379
+ if (args.idempotencyKey) {
380
+ headers['Idempotency-Key'] = args.idempotencyKey;
381
+ }
382
+ return {
383
+ method: args.method,
384
+ url: `${args.endpoint}${args.path}`,
385
+ headers,
386
+ body: args.body,
387
+ json: true,
388
+ };
389
+ }
390
+ function shouldFailOpen(error) {
391
+ var _a, _b;
392
+ if (error instanceof n8n_workflow_1.NodeOperationError)
393
+ return false;
394
+ const err = error;
395
+ const httpCode = (_a = (typeof err.httpCode === 'string' ? parseInt(err.httpCode, 10) : err.httpCode)) !== null && _a !== void 0 ? _a : (_b = err.context) === null || _b === void 0 ? void 0 : _b.statusCode;
396
+ if (typeof httpCode === 'number' && !Number.isNaN(httpCode)) {
397
+ return httpCode >= 500 && httpCode < 600;
398
+ }
399
+ return true;
400
+ }
401
+ function parseJsonParam(value) {
402
+ if (value === null || value === undefined)
403
+ return {};
404
+ if (typeof value === 'object')
405
+ return value;
406
+ if (typeof value === 'string') {
407
+ const trimmed = value.trim();
408
+ if (!trimmed)
409
+ return {};
410
+ try {
411
+ const parsed = JSON.parse(trimmed);
412
+ return (typeof parsed === 'object' && parsed !== null
413
+ ? parsed
414
+ : { value: parsed });
415
+ }
416
+ catch {
417
+ return { raw: value };
418
+ }
419
+ }
420
+ return {};
421
+ }
422
+ function extractApprovalData(resp, node) {
423
+ var _a;
424
+ const inner = resp.data;
425
+ if (!inner || typeof inner !== 'object') {
426
+ throw new n8n_workflow_1.NodeOperationError(node, 'AxonFlow returned an unexpected response shape from /api/v1/hitl/queue — missing `data` envelope. ' +
427
+ 'Check that the request is hitting the AxonFlow Agent directly (not a proxy that strips the wrapping object).');
428
+ }
429
+ return {
430
+ id: (_a = inner.id) !== null && _a !== void 0 ? _a : inner.approval_id,
431
+ status: inner.status,
432
+ expires_at: inner.expires_at,
433
+ };
434
+ }
435
+ //# sourceMappingURL=AxonFlow.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AxonFlow.node.js","sourceRoot":"","sources":["../../../nodes/AxonFlow/AxonFlow.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "node": "@axonflow/n8n-nodes-axonflow.axonFlow",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["Development"],
6
+ "resources": {
7
+ "credentialDocumentation": [
8
+ {
9
+ "url": "https://docs.getaxonflow.com/docs/integration/n8n/"
10
+ }
11
+ ],
12
+ "primaryDocumentation": [
13
+ {
14
+ "url": "https://docs.getaxonflow.com/docs/integration/n8n/"
15
+ }
16
+ ]
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="60" height="60" fill="none">
2
+ <rect width="64" height="64" rx="12" fill="#0F172A"/>
3
+ <path d="M16 44 L32 16 L48 44 Z" stroke="#22D3EE" stroke-width="3" stroke-linejoin="round" fill="none"/>
4
+ <circle cx="32" cy="36" r="3" fill="#22D3EE"/>
5
+ </svg>
@@ -0,0 +1,42 @@
1
+ # Example workflows
2
+
3
+ ## `governed-loan-workflow.json`
4
+
5
+ A complete HTTP-triggered loan-approval workflow that exercises all four AxonFlow operations.
6
+
7
+ ```
8
+ Loan Request (Webhook)
9
+
10
+
11
+ AxonFlow Check Policy ─── allowed=false ──▶ AxonFlow Wait for Approval
12
+ │ │
13
+ │ allowed=true ▼
14
+ │ Wait for Reviewer Webhook
15
+ │ │
16
+ ▼ ▼
17
+ Issue Loan (HTTP) ◀───────────────────────────── ┘
18
+
19
+ ├──▶ AxonFlow Record Decision ──▶ Respond
20
+ └──▶ AxonFlow Audit Log (Error)
21
+ ```
22
+
23
+ ### Import
24
+
25
+ In n8n: **Workflows → Import from File →** `governed-loan-workflow.json`.
26
+
27
+ You will need:
28
+
29
+ 1. An **AxonFlow API** credential filled in (endpoint + Client ID + User Token).
30
+ 2. The `n8n-nodes-axonflow` community node installed (Settings → Community Nodes).
31
+ 3. The `Issue Loan (HTTP)` node pointed at a real downstream service (it defaults to `https://loan-service.internal/v1/loans` as a placeholder).
32
+
33
+ ### How HITL resume works in this workflow
34
+
35
+ `AxonFlow Wait for Approval` creates the approval entry, then immediately returns the `approval_id`. The next node — a built-in n8n `Wait` configured for **On Webhook Call** mode — pauses the workflow.
36
+
37
+ Two resume paths are supported on v8.0.x:
38
+
39
+ 1. **Polling sidecar** (recommended for unattended workflows). A small process polls `GET /api/v1/hitl/queue/{approval_id}` on a short interval. When the request status changes to `approved` or `rejected`, the sidecar POSTs the reviewer decision to the Wait node's webhook URL. Reference implementation is documented in the [n8n integration docs](https://docs.getaxonflow.com/docs/integration/n8n/#hitl).
40
+ 2. **Manual portal resume** (works without any sidecar). The reviewer copies the Wait node's webhook URL from the n8n workflow editor and POSTs to it from the AxonFlow portal's approval-detail screen after deciding.
41
+
42
+ As of platform v8.1.0+, AxonFlow supports outbound webhooks via the `notify_url` field on `/api/v1/hitl/queue`. Pass the Wait node's webhook URL as `notify_url` and the platform will POST to it automatically on approval/rejection — the polling sidecar can be retired. The Wait-node side of the workflow is unchanged.
@@ -0,0 +1,211 @@
1
+ {
2
+ "name": "Governed Loan Approval (AxonFlow)",
3
+ "nodes": [
4
+ {
5
+ "parameters": {
6
+ "httpMethod": "POST",
7
+ "path": "loan-request",
8
+ "responseMode": "responseNode",
9
+ "options": {}
10
+ },
11
+ "id": "1",
12
+ "name": "Loan Request (Webhook)",
13
+ "type": "n8n-nodes-base.webhook",
14
+ "typeVersion": 2,
15
+ "position": [220, 300],
16
+ "webhookId": "loan-request-axonflow-demo"
17
+ },
18
+ {
19
+ "parameters": {
20
+ "operation": "checkPolicy",
21
+ "idempotencyKey": "={{ $execution.id }}-{{ $itemIndex }}-{{ $node.name }}",
22
+ "connectorType": "n8n",
23
+ "statement": "=approve_loan amount={{ $json.body.amount }} customer={{ $json.body.customer_id }}",
24
+ "mcpOperation": "execute",
25
+ "parameters": "={{ JSON.stringify({ amount: $json.body.amount, customer_id: $json.body.customer_id }) }}"
26
+ },
27
+ "id": "2",
28
+ "name": "AxonFlow Check Policy",
29
+ "type": "@axonflow/n8n-nodes-axonflow.axonFlow",
30
+ "typeVersion": 1,
31
+ "position": [460, 300],
32
+ "credentials": {
33
+ "axonFlowApi": {
34
+ "id": "axonflow-default",
35
+ "name": "AxonFlow API"
36
+ }
37
+ }
38
+ },
39
+ {
40
+ "parameters": {
41
+ "conditions": {
42
+ "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
43
+ "conditions": [
44
+ {
45
+ "leftValue": "={{ $json.allowed }}",
46
+ "rightValue": true,
47
+ "operator": { "type": "boolean", "operation": "equals" }
48
+ }
49
+ ],
50
+ "combinator": "and"
51
+ }
52
+ },
53
+ "id": "3",
54
+ "name": "Allowed?",
55
+ "type": "n8n-nodes-base.if",
56
+ "typeVersion": 2,
57
+ "position": [700, 300]
58
+ },
59
+ {
60
+ "parameters": {
61
+ "operation": "waitForApproval",
62
+ "idempotencyKey": "={{ $execution.id }}-{{ $itemIndex }}-{{ $node.name }}",
63
+ "requestType": "loan_approval",
64
+ "originalQuery": "=Approve loan for {{ $json.body.customer_id }} amount={{ $json.body.amount }}",
65
+ "triggeredPolicyId": "high-value-loan",
66
+ "triggeredPolicyName": "High Value Loan Approval",
67
+ "triggerReason": "=AxonFlow policy denied: {{ $('AxonFlow Check Policy').item.json.block_reason }}",
68
+ "severity": "high",
69
+ "limitWaitTime": 86400,
70
+ "requestContext": "={{ JSON.stringify($('Loan Request (Webhook)').item.json.body) }}"
71
+ },
72
+ "id": "4",
73
+ "name": "AxonFlow Wait for Approval",
74
+ "type": "@axonflow/n8n-nodes-axonflow.axonFlow",
75
+ "typeVersion": 1,
76
+ "position": [940, 460],
77
+ "credentials": {
78
+ "axonFlowApi": {
79
+ "id": "axonflow-default",
80
+ "name": "AxonFlow API"
81
+ }
82
+ }
83
+ },
84
+ {
85
+ "parameters": {
86
+ "resume": "webhook",
87
+ "options": {}
88
+ },
89
+ "id": "5",
90
+ "name": "Wait for Reviewer Webhook",
91
+ "type": "n8n-nodes-base.wait",
92
+ "typeVersion": 1.1,
93
+ "position": [1180, 460],
94
+ "webhookId": "axonflow-approval-resume"
95
+ },
96
+ {
97
+ "parameters": {
98
+ "method": "POST",
99
+ "url": "=https://loan-service.internal/v1/loans",
100
+ "sendBody": true,
101
+ "specifyBody": "json",
102
+ "jsonBody": "={{ JSON.stringify($('Loan Request (Webhook)').item.json.body) }}",
103
+ "options": {}
104
+ },
105
+ "id": "6",
106
+ "name": "Issue Loan (HTTP)",
107
+ "type": "n8n-nodes-base.httpRequest",
108
+ "typeVersion": 4.2,
109
+ "position": [1420, 300],
110
+ "onError": "continueErrorOutput"
111
+ },
112
+ {
113
+ "parameters": {
114
+ "operation": "recordDecision",
115
+ "idempotencyKey": "={{ $execution.id }}-{{ $itemIndex }}-{{ $node.name }}",
116
+ "toolName": "issue_loan",
117
+ "workflowId": "={{ $workflow.id }}",
118
+ "stepId": "={{ $node.name }}",
119
+ "auditInput": "={{ JSON.stringify($('Loan Request (Webhook)').item.json.body) }}",
120
+ "auditOutput": "={{ JSON.stringify($json) }}",
121
+ "auditSuccess": true,
122
+ "auditErrorMessage": ""
123
+ },
124
+ "id": "7",
125
+ "name": "AxonFlow Record Decision",
126
+ "type": "@axonflow/n8n-nodes-axonflow.axonFlow",
127
+ "typeVersion": 1,
128
+ "position": [1660, 300],
129
+ "credentials": {
130
+ "axonFlowApi": {
131
+ "id": "axonflow-default",
132
+ "name": "AxonFlow API"
133
+ }
134
+ }
135
+ },
136
+ {
137
+ "parameters": {
138
+ "operation": "auditLog",
139
+ "idempotencyKey": "={{ $execution.id }}-{{ $itemIndex }}-{{ $node.name }}",
140
+ "toolName": "issue_loan",
141
+ "workflowId": "={{ $workflow.id }}",
142
+ "stepId": "issue-loan-error",
143
+ "auditInput": "={{ JSON.stringify($('Loan Request (Webhook)').item.json.body) }}",
144
+ "auditOutput": "={{ JSON.stringify($json) }}",
145
+ "auditSuccess": false,
146
+ "auditErrorMessage": "=Loan issuance failed: {{ $json.error || 'unknown' }}"
147
+ },
148
+ "id": "8",
149
+ "name": "AxonFlow Audit Log (Error)",
150
+ "type": "@axonflow/n8n-nodes-axonflow.axonFlow",
151
+ "typeVersion": 1,
152
+ "position": [1660, 600],
153
+ "credentials": {
154
+ "axonFlowApi": {
155
+ "id": "axonflow-default",
156
+ "name": "AxonFlow API"
157
+ }
158
+ }
159
+ },
160
+ {
161
+ "parameters": {
162
+ "respondWith": "json",
163
+ "responseBody": "={{ JSON.stringify({ status: 'recorded', decision: $('AxonFlow Record Decision').item.json }) }}",
164
+ "options": {}
165
+ },
166
+ "id": "9",
167
+ "name": "Respond",
168
+ "type": "n8n-nodes-base.respondToWebhook",
169
+ "typeVersion": 1.1,
170
+ "position": [1900, 300]
171
+ }
172
+ ],
173
+ "connections": {
174
+ "Loan Request (Webhook)": {
175
+ "main": [[{ "node": "AxonFlow Check Policy", "type": "main", "index": 0 }]]
176
+ },
177
+ "AxonFlow Check Policy": {
178
+ "main": [[{ "node": "Allowed?", "type": "main", "index": 0 }]]
179
+ },
180
+ "Allowed?": {
181
+ "main": [
182
+ [{ "node": "Issue Loan (HTTP)", "type": "main", "index": 0 }],
183
+ [{ "node": "AxonFlow Wait for Approval", "type": "main", "index": 0 }]
184
+ ]
185
+ },
186
+ "AxonFlow Wait for Approval": {
187
+ "main": [[{ "node": "Wait for Reviewer Webhook", "type": "main", "index": 0 }]]
188
+ },
189
+ "Wait for Reviewer Webhook": {
190
+ "main": [[{ "node": "Issue Loan (HTTP)", "type": "main", "index": 0 }]]
191
+ },
192
+ "Issue Loan (HTTP)": {
193
+ "main": [
194
+ [{ "node": "AxonFlow Record Decision", "type": "main", "index": 0 }],
195
+ [{ "node": "AxonFlow Audit Log (Error)", "type": "main", "index": 0 }]
196
+ ]
197
+ },
198
+ "AxonFlow Record Decision": {
199
+ "main": [[{ "node": "Respond", "type": "main", "index": 0 }]]
200
+ }
201
+ },
202
+ "settings": {
203
+ "executionOrder": "v1"
204
+ },
205
+ "tags": [
206
+ { "name": "axonflow-demo" }
207
+ ],
208
+ "meta": {
209
+ "templateCredsSetupCompleted": false
210
+ }
211
+ }
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@axonflow/n8n-nodes-axonflow",
3
+ "version": "1.0.0",
4
+ "description": "AxonFlow API integration for n8n — call AxonFlow policy and HITL endpoints from your workflows.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "axonflow",
8
+ "policy",
9
+ "hitl"
10
+ ],
11
+ "license": "MIT",
12
+ "homepage": "https://github.com/getaxonflow/axonflow-n8n-node",
13
+ "author": {
14
+ "name": "AxonFlow",
15
+ "email": "hello@getaxonflow.com",
16
+ "url": "https://getaxonflow.com"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/getaxonflow/axonflow-n8n-node.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/getaxonflow/axonflow-n8n-node/issues"
24
+ },
25
+ "engines": {
26
+ "node": ">=18.10"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc && node ./scripts/copy-assets.js",
30
+ "lint": "eslint nodes credentials package.json",
31
+ "test": "node --test --import tsx test/AxonFlow.node.test.ts test/AxonFlowApi.credentials.test.ts",
32
+ "format": "prettier nodes credentials --write",
33
+ "prepublishOnly": "npm run build"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "examples"
38
+ ],
39
+ "n8n": {
40
+ "n8nNodesApiVersion": 1,
41
+ "credentials": [
42
+ "dist/credentials/AxonFlowApi.credentials.js"
43
+ ],
44
+ "nodes": [
45
+ "dist/nodes/AxonFlow/AxonFlow.node.js"
46
+ ]
47
+ },
48
+ "peerDependencies": {
49
+ "n8n-workflow": "*"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.11.0",
53
+ "@typescript-eslint/eslint-plugin": "^7.15.0",
54
+ "@typescript-eslint/parser": "^7.15.0",
55
+ "eslint": "^8.57.0",
56
+ "eslint-plugin-n8n-nodes-base": "^1.16.3",
57
+ "n8n-workflow": "^1.82.0",
58
+ "prettier": "^3.3.3",
59
+ "tsx": "^4.16.0",
60
+ "typescript": "^5.4.0"
61
+ }
62
+ }