@naturali/cli 0.69.0 → 0.70.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.
Files changed (2) hide show
  1. package/dist/index.mjs +3005 -856
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -14,7 +14,7 @@ var __exportAll = (all, no_symbols) => {
14
14
  };
15
15
  //#endregion
16
16
  //#region package.json
17
- var version = "0.69.0";
17
+ var version = "0.70.0";
18
18
  //#endregion
19
19
  //#region ../sdk/src/generated/core/bodySerializer.gen.ts
20
20
  const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
@@ -2132,6 +2132,219 @@ var Models = class {
2132
2132
  });
2133
2133
  }
2134
2134
  };
2135
+ var Orchestrations = class {
2136
+ /**
2137
+ * List orchestrations
2138
+ *
2139
+ * Returns orchestrations accessible to the caller.
2140
+ */
2141
+ static listOrchestrations(options) {
2142
+ return (options.client ?? client).get({
2143
+ url: "/v1/projects/{project_id}/orchestrations",
2144
+ ...options
2145
+ });
2146
+ }
2147
+ /**
2148
+ * Create an orchestration
2149
+ *
2150
+ * Creates a new orchestration (pipeline) definition in the project.
2151
+ */
2152
+ static createOrchestration(options) {
2153
+ return (options.client ?? client).post({
2154
+ url: "/v1/projects/{project_id}/orchestrations",
2155
+ ...options,
2156
+ headers: {
2157
+ "Content-Type": "application/json",
2158
+ ...options.headers
2159
+ }
2160
+ });
2161
+ }
2162
+ /**
2163
+ * Validate an orchestration graph
2164
+ *
2165
+ * Statically validates an orchestration graph without persisting anything. Checks that every node has its required field, node ids are unique, edges reference existing nodes, the graph is acyclic (unless it contains a loop node), and every `input_mapping` `{"var": "..."}` reference resolves to a state key written by an upstream node or seeded by `input_schema`. Returns blocking `errors` and non-blocking `warnings` (e.g. a state key only written on a conditional branch). The same `errors` checks are enforced on create and update, which fail with `400` when any error is present.
2166
+ *
2167
+ */
2168
+ static validateOrchestration(options) {
2169
+ return (options.client ?? client).post({
2170
+ url: "/v1/projects/{project_id}/orchestrations/validate",
2171
+ ...options,
2172
+ headers: {
2173
+ "Content-Type": "application/json",
2174
+ ...options.headers
2175
+ }
2176
+ });
2177
+ }
2178
+ /**
2179
+ * Get orchestration queue stats
2180
+ *
2181
+ * Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`. A project-scoped caller sees only their own projects under `per_project`.
2182
+ *
2183
+ */
2184
+ static getQueueStats(options) {
2185
+ return (options.client ?? client).get({
2186
+ security: [{
2187
+ scheme: "bearer",
2188
+ type: "http"
2189
+ }],
2190
+ url: "/v1/projects/{project_id}/orchestrations/queue/stats",
2191
+ ...options
2192
+ });
2193
+ }
2194
+ /**
2195
+ * Delete an orchestration
2196
+ *
2197
+ * Deletes an orchestration definition and all its runs.
2198
+ */
2199
+ static deleteOrchestration(options) {
2200
+ return (options.client ?? client).delete({
2201
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}",
2202
+ ...options
2203
+ });
2204
+ }
2205
+ /**
2206
+ * Get an orchestration
2207
+ *
2208
+ * Returns the orchestration with nodes and edges.
2209
+ */
2210
+ static getOrchestration(options) {
2211
+ return (options.client ?? client).get({
2212
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}",
2213
+ ...options
2214
+ });
2215
+ }
2216
+ /**
2217
+ * Update an orchestration
2218
+ *
2219
+ * Partially updates an orchestration definition.
2220
+ */
2221
+ static updateOrchestration(options) {
2222
+ return (options.client ?? client).patch({
2223
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}",
2224
+ ...options,
2225
+ headers: {
2226
+ "Content-Type": "application/json",
2227
+ ...options.headers
2228
+ }
2229
+ });
2230
+ }
2231
+ /**
2232
+ * List an orchestration's graph versions
2233
+ *
2234
+ * Returns the orchestration's archived graphs, newest first. A version is written on create and on every subsequent write that changes the graph (`nodes`, `edges`, `state_schema`, `input_schema`) — through the REST API or a formation apply alike. Metadata-only edits (name, description) do not archive a version. See [Versioning](/docs/modules/orchestrations#versioning).
2235
+ *
2236
+ */
2237
+ static listOrchestrationVersions(options) {
2238
+ return (options.client ?? client).get({
2239
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}/versions",
2240
+ ...options
2241
+ });
2242
+ }
2243
+ /**
2244
+ * Fetch an archived orchestration version
2245
+ *
2246
+ * Returns the exact graph a given version describes. Every run records the version it started on in `orchestration_version` and executes that graph for its whole life, so this is how you read the topology a run actually took — including a run whose orchestration has been rewired since.
2247
+ *
2248
+ */
2249
+ static getOrchestrationVersion(options) {
2250
+ return (options.client ?? client).get({
2251
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}/versions/{version}",
2252
+ ...options
2253
+ });
2254
+ }
2255
+ /**
2256
+ * Restore an archived orchestration graph
2257
+ *
2258
+ * Writes an archived version's graph back as the orchestration's live definition, which archives it again as a **new** version rather than rewinding the counter — so a run pinned to any version in between still resolves the graph it started on.
2259
+ *
2260
+ * The restore runs through the ordinary update path, so the archived graph goes through the same static validation as an authored one. Node resource references (`agent_id`, `tool_id`, `orchestration_id`) resolve when a run reaches the node, so a target deleted since the snapshot was taken restores cleanly and surfaces as a failed run rather than a `400`. Restoring the graph the orchestration already holds is a no-op and archives nothing. Runs already in flight are unaffected either way — a restore is an ordinary edit, and pinning is what keeps it from reaching them.
2261
+ *
2262
+ */
2263
+ static restoreOrchestrationVersion(options) {
2264
+ return (options.client ?? client).post({
2265
+ url: "/v1/projects/{project_id}/orchestrations/{orchestration_id}/versions/{version}/restore",
2266
+ ...options,
2267
+ headers: {
2268
+ "Content-Type": "application/json",
2269
+ ...options.headers
2270
+ }
2271
+ });
2272
+ }
2273
+ /**
2274
+ * List orchestration runs
2275
+ *
2276
+ * Returns orchestration runs the caller can access, optionally filtered by orchestration.
2277
+ */
2278
+ static listOrchestrationRuns(options) {
2279
+ return (options.client ?? client).get({
2280
+ url: "/v1/projects/{project_id}/orchestration-runs",
2281
+ ...options
2282
+ });
2283
+ }
2284
+ /**
2285
+ * Start an orchestration run
2286
+ *
2287
+ * Creates a new run for the orchestration named by orchestration_id. By default the run executes durably in the background: the response returns immediately with status "queued" (a worker then claims it and moves it to "running") and progress is observed via get-orchestration-run or run lifecycle webhook events (orchestration_runs.started/awaiting_input/succeeded/failed). Delay and poll waits park the run as "sleeping" and are woken by a background scheduler, surviving restarts. Pass wait=true to block until the run reaches a terminal or awaiting_input state.
2288
+ */
2289
+ static startOrchestrationRun(options) {
2290
+ return (options.client ?? client).post({
2291
+ url: "/v1/projects/{project_id}/orchestration-runs",
2292
+ ...options,
2293
+ headers: {
2294
+ "Content-Type": "application/json",
2295
+ ...options.headers
2296
+ }
2297
+ });
2298
+ }
2299
+ /**
2300
+ * Cancel an orchestration run
2301
+ *
2302
+ * Cancels a run that has not yet reached a terminal state.
2303
+ */
2304
+ static cancelOrchestrationRun(options) {
2305
+ return (options.client ?? client).post({
2306
+ url: "/v1/projects/{project_id}/orchestration-runs/{orchestration_run_id}/cancel",
2307
+ ...options
2308
+ });
2309
+ }
2310
+ /**
2311
+ * Submit human input
2312
+ *
2313
+ * Provides human input to a run that is awaiting_input at a human node.
2314
+ */
2315
+ static submitHumanInput(options) {
2316
+ return (options.client ?? client).post({
2317
+ url: "/v1/projects/{project_id}/orchestration-runs/{orchestration_run_id}/human-input",
2318
+ ...options,
2319
+ headers: {
2320
+ "Content-Type": "application/json",
2321
+ ...options.headers
2322
+ }
2323
+ });
2324
+ }
2325
+ /**
2326
+ * Resume an orchestration run
2327
+ *
2328
+ * Re-drives an awaiting_input orchestration run from its last checkpoint. This does not satisfy the pause itself — it carries no node_id or payload, so a run parked on a human or webhook-receive node re-parks on the same node. Use submit-human-input to supply the awaited payload and advance the run.
2329
+ */
2330
+ static resumeOrchestrationRun(options) {
2331
+ return (options.client ?? client).post({
2332
+ url: "/v1/projects/{project_id}/orchestration-runs/{orchestration_run_id}/resume",
2333
+ ...options
2334
+ });
2335
+ }
2336
+ /**
2337
+ * Get an orchestration run
2338
+ *
2339
+ * Returns the status, state, and artifacts of a specific run.
2340
+ */
2341
+ static getOrchestrationRun(options) {
2342
+ return (options.client ?? client).get({
2343
+ url: "/v1/projects/{project_id}/orchestration-runs/{orchestration_run_id}",
2344
+ ...options
2345
+ });
2346
+ }
2347
+ };
2135
2348
  var Projects = class {
2136
2349
  /**
2137
2350
  * List projects
@@ -2485,6 +2698,97 @@ var Sessions = class {
2485
2698
  });
2486
2699
  }
2487
2700
  };
2701
+ var Tasks = class {
2702
+ /**
2703
+ * List tasks
2704
+ *
2705
+ * Lists tasks (the board query). Filter by workflow, state, status, or assignee — `GET /tasks?workflow_id=...&state=...` is one board column.
2706
+ */
2707
+ static listTasks(options) {
2708
+ return (options.client ?? client).get({
2709
+ url: "/v1/projects/{project_id}/tasks",
2710
+ ...options
2711
+ });
2712
+ }
2713
+ /**
2714
+ * Create a task
2715
+ *
2716
+ * Creates a task bound to a workflow. By default the task is placed in the workflow's initial state; passing `state` places it directly in that named state instead — an alternate entry point for starting a task mid-flow (e.g. "a new recorte for an existing theme by id"), rather than re-submitting from the initial state and hoping a guard or similarity gate recognizes it. Entering the resulting state, initial or named, behaves identically: that state's `on_enter` automation fires and its `stalled_after` clock arms.
2717
+ */
2718
+ static createTask(options) {
2719
+ return (options.client ?? client).post({
2720
+ url: "/v1/projects/{project_id}/tasks",
2721
+ ...options,
2722
+ headers: {
2723
+ "Content-Type": "application/json",
2724
+ ...options.headers
2725
+ }
2726
+ });
2727
+ }
2728
+ /**
2729
+ * Delete a task
2730
+ *
2731
+ * Deletes a task. Its transition history cascades.
2732
+ */
2733
+ static deleteTask(options) {
2734
+ return (options.client ?? client).delete({
2735
+ url: "/v1/projects/{project_id}/tasks/{task_id}",
2736
+ ...options
2737
+ });
2738
+ }
2739
+ /**
2740
+ * Get a task
2741
+ *
2742
+ * Retrieves a task, including its active dispatch and automation status.
2743
+ */
2744
+ static getTask(options) {
2745
+ return (options.client ?? client).get({
2746
+ url: "/v1/projects/{project_id}/tasks/{task_id}",
2747
+ ...options
2748
+ });
2749
+ }
2750
+ /**
2751
+ * Update a task
2752
+ *
2753
+ * Updates a task's payload, title, or assignee. `state` is never directly writable — move it with a transition; sending a `state` field is rejected as an unknown field (`VALIDATION_FAILED`). `payload` is shallow-merged over the existing payload (PATCH semantics): keys the request omits are preserved. The payload is caller-owned; the automation result lives in the read-only `last_result` field, which no patch can reach. The merged payload is validated against the workflow's `payload_schema`.
2754
+ */
2755
+ static updateTask(options) {
2756
+ return (options.client ?? client).patch({
2757
+ url: "/v1/projects/{project_id}/tasks/{task_id}",
2758
+ ...options,
2759
+ headers: {
2760
+ "Content-Type": "application/json",
2761
+ ...options.headers
2762
+ }
2763
+ });
2764
+ }
2765
+ /**
2766
+ * Transition a task
2767
+ *
2768
+ * Fires a named transition on a task. The transition must exist in the workflow and be valid from the task's current state; its guard must pass. This is the single path every state change routes through. A transition declaring `requires_approval` does not move the task — it parks a pending ApprovalItem and returns the task with `pending_transition` set; the move applies only when the approval is approved.
2769
+ */
2770
+ static transitionTask(options) {
2771
+ return (options.client ?? client).post({
2772
+ url: "/v1/projects/{project_id}/tasks/{task_id}/transitions",
2773
+ ...options,
2774
+ headers: {
2775
+ "Content-Type": "application/json",
2776
+ ...options.headers
2777
+ }
2778
+ });
2779
+ }
2780
+ /**
2781
+ * Get task history
2782
+ *
2783
+ * Returns the append-only transition history of a task.
2784
+ */
2785
+ static getTaskHistory(options) {
2786
+ return (options.client ?? client).get({
2787
+ url: "/v1/projects/{project_id}/tasks/{task_id}/history",
2788
+ ...options
2789
+ });
2790
+ }
2791
+ };
2488
2792
  var Tools = class {
2489
2793
  /**
2490
2794
  * List tools
@@ -2620,27 +2924,26 @@ var Traces = class {
2620
2924
  });
2621
2925
  }
2622
2926
  };
2623
- var Users = class {
2927
+ var Triggers = class {
2624
2928
  /**
2625
- * Get the current user
2929
+ * List triggers
2626
2930
  *
2627
- * Returns the account the presented credential resolves to.
2931
+ * Lists triggers. Filter by project, starter type, or target type.
2628
2932
  */
2629
- static getCurrentUser(options) {
2630
- return (options?.client ?? client).get({
2631
- url: "/v1/users/me",
2933
+ static listTriggers(options) {
2934
+ return (options.client ?? client).get({
2935
+ url: "/v1/projects/{project_id}/triggers",
2632
2936
  ...options
2633
2937
  });
2634
2938
  }
2635
2939
  /**
2636
- * Update the current user
2637
- *
2638
- * Edits the account's display name. `name` is required in the body — send null to clear it — so a request that misspelled the field is rejected rather than answered with a silent 200.
2940
+ * Create a trigger
2639
2941
  *
2942
+ * Creates a new trigger for a project
2640
2943
  */
2641
- static updateCurrentUser(options) {
2642
- return (options.client ?? client).patch({
2643
- url: "/v1/users/me",
2944
+ static createTrigger(options) {
2945
+ return (options.client ?? client).post({
2946
+ url: "/v1/projects/{project_id}/triggers",
2644
2947
  ...options,
2645
2948
  headers: {
2646
2949
  "Content-Type": "application/json",
@@ -2648,30 +2951,51 @@ var Users = class {
2648
2951
  }
2649
2952
  });
2650
2953
  }
2651
- };
2652
- var Webhooks = class {
2653
2954
  /**
2654
- * List webhooks
2955
+ * Delete a trigger
2655
2956
  *
2656
- * The endpoints registered in the project, newest first.
2957
+ * Deletes a trigger
2657
2958
  */
2658
- static listWebhooks(options) {
2959
+ static deleteTrigger(options) {
2960
+ return (options.client ?? client).delete({
2961
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}",
2962
+ ...options
2963
+ });
2964
+ }
2965
+ /**
2966
+ * Get a trigger
2967
+ *
2968
+ * Retrieves the details of a specific trigger
2969
+ */
2970
+ static getTrigger(options) {
2659
2971
  return (options.client ?? client).get({
2660
- url: "/v1/projects/{project_id}/webhooks",
2972
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}",
2661
2973
  ...options
2662
2974
  });
2663
2975
  }
2664
2976
  /**
2665
- * Create a webhook
2977
+ * Update a trigger
2666
2978
  *
2667
- * Register an endpoint and subscribe it to one or more event types.
2668
- * The response carries `secret` — the signing key, in plaintext. **This is the only time it is returned.** Store it where your receiver can read it; if you lose it, rotate rather than re-create, so the endpoint keeps its delivery history.
2669
- * Returns `501` on a deployment with no credential-sealing key configured, since the secret could not then be stored safely.
2979
+ * Updates an existing trigger's configuration. The type is immutable.
2980
+ */
2981
+ static updateTrigger(options) {
2982
+ return (options.client ?? client).patch({
2983
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}",
2984
+ ...options,
2985
+ headers: {
2986
+ "Content-Type": "application/json",
2987
+ ...options.headers
2988
+ }
2989
+ });
2990
+ }
2991
+ /**
2992
+ * Fire a trigger
2670
2993
  *
2994
+ * Fires a trigger synchronously and returns the terminal firing record. The firing itself always settles here; an `eval` target's run is queued rather than executed inline, so the record names a `queued` run to poll.
2671
2995
  */
2672
- static createWebhook(options) {
2996
+ static fireTrigger(options) {
2673
2997
  return (options.client ?? client).post({
2674
- url: "/v1/projects/{project_id}/webhooks",
2998
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}/fire",
2675
2999
  ...options,
2676
3000
  headers: {
2677
3001
  "Content-Type": "application/json",
@@ -2680,19 +3004,123 @@ var Webhooks = class {
2680
3004
  });
2681
3005
  }
2682
3006
  /**
2683
- * Delete a webhook
2684
- *
2685
- * Removes the endpoint and its delivery records. To stop deliveries while keeping the audit trail, `PATCH` it to `active: false` instead.
3007
+ * Get trigger secret
2686
3008
  *
3009
+ * Retrieves the signing secret for a webhook trigger
2687
3010
  */
2688
- static deleteWebhook(options) {
2689
- return (options.client ?? client).delete({
2690
- url: "/v1/projects/{project_id}/webhooks/{webhook_id}",
3011
+ static getTriggerSecret(options) {
3012
+ return (options.client ?? client).get({
3013
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}/secret",
2691
3014
  ...options
2692
3015
  });
2693
3016
  }
2694
3017
  /**
2695
- * Get a webhook
3018
+ * Rotate trigger secret
3019
+ *
3020
+ * Rotates the signing secret for a webhook trigger
3021
+ */
3022
+ static rotateTriggerSecret(options) {
3023
+ return (options.client ?? client).post({
3024
+ url: "/v1/projects/{project_id}/triggers/{trigger_id}/rotate-secret",
3025
+ ...options
3026
+ });
3027
+ }
3028
+ /**
3029
+ * List trigger firings
3030
+ *
3031
+ * Lists firings for a trigger (trigger_id is required).
3032
+ */
3033
+ static listTriggerFirings(options) {
3034
+ return (options.client ?? client).get({
3035
+ url: "/v1/projects/{project_id}/trigger-firings",
3036
+ ...options
3037
+ });
3038
+ }
3039
+ /**
3040
+ * Get a trigger firing
3041
+ *
3042
+ * Retrieves the details of a specific trigger firing
3043
+ */
3044
+ static getTriggerFiring(options) {
3045
+ return (options.client ?? client).get({
3046
+ url: "/v1/projects/{project_id}/trigger-firings/{firing_id}",
3047
+ ...options
3048
+ });
3049
+ }
3050
+ };
3051
+ var Users = class {
3052
+ /**
3053
+ * Get the current user
3054
+ *
3055
+ * Returns the account the presented credential resolves to.
3056
+ */
3057
+ static getCurrentUser(options) {
3058
+ return (options?.client ?? client).get({
3059
+ url: "/v1/users/me",
3060
+ ...options
3061
+ });
3062
+ }
3063
+ /**
3064
+ * Update the current user
3065
+ *
3066
+ * Edits the account's display name. `name` is required in the body — send null to clear it — so a request that misspelled the field is rejected rather than answered with a silent 200.
3067
+ *
3068
+ */
3069
+ static updateCurrentUser(options) {
3070
+ return (options.client ?? client).patch({
3071
+ url: "/v1/users/me",
3072
+ ...options,
3073
+ headers: {
3074
+ "Content-Type": "application/json",
3075
+ ...options.headers
3076
+ }
3077
+ });
3078
+ }
3079
+ };
3080
+ var Webhooks = class {
3081
+ /**
3082
+ * List webhooks
3083
+ *
3084
+ * The endpoints registered in the project, newest first.
3085
+ */
3086
+ static listWebhooks(options) {
3087
+ return (options.client ?? client).get({
3088
+ url: "/v1/projects/{project_id}/webhooks",
3089
+ ...options
3090
+ });
3091
+ }
3092
+ /**
3093
+ * Create a webhook
3094
+ *
3095
+ * Register an endpoint and subscribe it to one or more event types.
3096
+ * The response carries `secret` — the signing key, in plaintext. **This is the only time it is returned.** Store it where your receiver can read it; if you lose it, rotate rather than re-create, so the endpoint keeps its delivery history.
3097
+ * Returns `501` on a deployment with no credential-sealing key configured, since the secret could not then be stored safely.
3098
+ *
3099
+ */
3100
+ static createWebhook(options) {
3101
+ return (options.client ?? client).post({
3102
+ url: "/v1/projects/{project_id}/webhooks",
3103
+ ...options,
3104
+ headers: {
3105
+ "Content-Type": "application/json",
3106
+ ...options.headers
3107
+ }
3108
+ });
3109
+ }
3110
+ /**
3111
+ * Delete a webhook
3112
+ *
3113
+ * Removes the endpoint and its delivery records. To stop deliveries while keeping the audit trail, `PATCH` it to `active: false` instead.
3114
+ *
3115
+ */
3116
+ static deleteWebhook(options) {
3117
+ return (options.client ?? client).delete({
3118
+ url: "/v1/projects/{project_id}/webhooks/{webhook_id}",
3119
+ ...options
3120
+ });
3121
+ }
3122
+ /**
3123
+ * Get a webhook
2696
3124
  */
2697
3125
  static getWebhook(options) {
2698
3126
  return (options.client ?? client).get({
@@ -2769,6 +3197,113 @@ var Webhooks = class {
2769
3197
  });
2770
3198
  }
2771
3199
  };
3200
+ var Workflows = class {
3201
+ /**
3202
+ * List workflows
3203
+ *
3204
+ * Lists workflow definitions in a project.
3205
+ */
3206
+ static listWorkflows(options) {
3207
+ return (options.client ?? client).get({
3208
+ url: "/v1/projects/{project_id}/workflows",
3209
+ ...options
3210
+ });
3211
+ }
3212
+ /**
3213
+ * Create a workflow
3214
+ *
3215
+ * Creates a new workflow definition. The definition is statically validated.
3216
+ */
3217
+ static createWorkflow(options) {
3218
+ return (options.client ?? client).post({
3219
+ url: "/v1/projects/{project_id}/workflows",
3220
+ ...options,
3221
+ headers: {
3222
+ "Content-Type": "application/json",
3223
+ ...options.headers
3224
+ }
3225
+ });
3226
+ }
3227
+ /**
3228
+ * Delete a workflow
3229
+ *
3230
+ * Deletes a workflow. Rejected while open tasks exist.
3231
+ */
3232
+ static deleteWorkflow(options) {
3233
+ return (options.client ?? client).delete({
3234
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}",
3235
+ ...options
3236
+ });
3237
+ }
3238
+ /**
3239
+ * Get a workflow
3240
+ *
3241
+ * Retrieves a workflow definition.
3242
+ */
3243
+ static getWorkflow(options) {
3244
+ return (options.client ?? client).get({
3245
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}",
3246
+ ...options
3247
+ });
3248
+ }
3249
+ /**
3250
+ * Update a workflow
3251
+ *
3252
+ * Updates a workflow definition. Structural changes (states/transitions) are re-validated. Existing tasks in a removed state stay put but can only leave via transitions valid in the new definition.
3253
+ */
3254
+ static updateWorkflow(options) {
3255
+ return (options.client ?? client).patch({
3256
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}",
3257
+ ...options,
3258
+ headers: {
3259
+ "Content-Type": "application/json",
3260
+ ...options.headers
3261
+ }
3262
+ });
3263
+ }
3264
+ /**
3265
+ * List a workflow's versions
3266
+ *
3267
+ * Returns the workflow's archived state machines, newest first. A version is written on create and on every subsequent write that changes the definition (`states`, `transitions`, `payload_schema`) — through the REST API or a formation apply alike. Metadata-only edits (name, description) do not archive a version. See [Versioning](/docs/modules/workflows#versioning).
3268
+ *
3269
+ */
3270
+ static listWorkflowVersions(options) {
3271
+ return (options.client ?? client).get({
3272
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}/versions",
3273
+ ...options
3274
+ });
3275
+ }
3276
+ /**
3277
+ * Fetch an archived workflow version
3278
+ *
3279
+ * Returns the exact state machine a given version describes. Every task records the version it entered on in `workflow_version` and runs on that machine for its whole life, so this is how you read the definition a task is actually being validated against — including a task whose workflow has been rewired since.
3280
+ *
3281
+ */
3282
+ static getWorkflowVersion(options) {
3283
+ return (options.client ?? client).get({
3284
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}/versions/{version}",
3285
+ ...options
3286
+ });
3287
+ }
3288
+ /**
3289
+ * Restore an archived workflow state machine
3290
+ *
3291
+ * Writes an archived version's state machine back as the workflow's live definition, which archives it again as a **new** version rather than rewinding the counter — so a task pinned to any version in between still runs on the machine it entered on.
3292
+ *
3293
+ * The restore runs through the ordinary update path, so the archived definition goes through the same validation as an authored one. That includes resolving every `on_enter` dispatch target, so restoring a version whose agent or orchestration has since been deleted fails with `400` rather than writing a definition that would strand a task on entry. Restoring the definition the workflow already holds is a no-op and archives nothing. Tasks already in flight are unaffected either way — a restore is an ordinary edit, and pinning is what keeps it from reaching them.
3294
+ *
3295
+ */
3296
+ static restoreWorkflowVersion(options) {
3297
+ return (options.client ?? client).post({
3298
+ url: "/v1/projects/{project_id}/workflows/{workflow_id}/versions/{version}/restore",
3299
+ ...options,
3300
+ headers: {
3301
+ "Content-Type": "application/json",
3302
+ ...options.headers
3303
+ }
3304
+ });
3305
+ }
3306
+ };
2772
3307
  //#endregion
2773
3308
  //#region ../sdk/src/naturaliClient.ts
2774
3309
  /**
@@ -2829,13 +3364,17 @@ var NaturaliClient = class {
2829
3364
  generations;
2830
3365
  modelRoutes;
2831
3366
  models;
3367
+ orchestrations;
2832
3368
  projects;
2833
3369
  secrets;
2834
3370
  sessions;
3371
+ tasks;
2835
3372
  tools;
2836
3373
  traces;
3374
+ triggers;
2837
3375
  users;
2838
3376
  webhooks;
3377
+ workflows;
2839
3378
  /** The underlying HTTP client, for interceptors or one-off requests. */
2840
3379
  http;
2841
3380
  constructor({ token, headers } = {}) {
@@ -2859,13 +3398,17 @@ var NaturaliClient = class {
2859
3398
  this.generations = bindResource(Generations, this.http);
2860
3399
  this.modelRoutes = bindResource(ModelRoutes, this.http);
2861
3400
  this.models = bindResource(Models, this.http);
3401
+ this.orchestrations = bindResource(Orchestrations, this.http);
2862
3402
  this.projects = bindResource(Projects, this.http);
2863
3403
  this.secrets = bindResource(Secrets, this.http);
2864
3404
  this.sessions = bindResource(Sessions, this.http);
3405
+ this.tasks = bindResource(Tasks, this.http);
2865
3406
  this.tools = bindResource(Tools, this.http);
2866
3407
  this.traces = bindResource(Traces, this.http);
3408
+ this.triggers = bindResource(Triggers, this.http);
2867
3409
  this.users = bindResource(Users, this.http);
2868
3410
  this.webhooks = bindResource(Webhooks, this.http);
3411
+ this.workflows = bindResource(Workflows, this.http);
2869
3412
  }
2870
3413
  };
2871
3414
  //#endregion
@@ -2885,13 +3428,17 @@ var src_exports = /* @__PURE__ */ __exportAll({
2885
3428
  ModelRoutes: () => ModelRoutes,
2886
3429
  Models: () => Models,
2887
3430
  NaturaliClient: () => NaturaliClient,
3431
+ Orchestrations: () => Orchestrations,
2888
3432
  Projects: () => Projects,
2889
3433
  Secrets: () => Secrets,
2890
3434
  Sessions: () => Sessions,
3435
+ Tasks: () => Tasks,
2891
3436
  Tools: () => Tools,
2892
3437
  Traces: () => Traces,
3438
+ Triggers: () => Triggers,
2893
3439
  Users: () => Users,
2894
3440
  Webhooks: () => Webhooks,
3441
+ Workflows: () => Workflows,
2895
3442
  createClient: () => createClient,
2896
3443
  createConfig: () => createConfig
2897
3444
  });
@@ -7677,66 +8224,44 @@ const routes = {
7677
8224
  }
7678
8225
  ]
7679
8226
  },
7680
- "list-projects": {
7681
- serviceClass: "Projects",
7682
- operationId: "listProjects",
7683
- description: "Lists the projects the caller is a member of. A project-scoped API key lists only its own project.",
7684
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
7685
- httpMethod: "get",
7686
- pathParams: [],
7687
- queryParams: ["limit", "cursor"],
7688
- flags: [{
7689
- "name": "limit",
7690
- "description": "Maximum items per page — an integer from 1 to 100 (default 20).",
7691
- "required": false,
7692
- "type": "integer",
7693
- "in": "query"
7694
- }, {
7695
- "name": "cursor",
7696
- "description": "Opaque pagination cursor from a previous response's next_cursor.",
7697
- "required": false,
7698
- "type": "string",
7699
- "in": "query"
7700
- }]
7701
- },
7702
- "create-project": {
7703
- serviceClass: "Projects",
7704
- operationId: "createProject",
7705
- description: "Creates a project (one per client or per environment).",
7706
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
7707
- httpMethod: "post",
7708
- pathParams: [],
7709
- queryParams: [],
7710
- flags: [{
7711
- "name": "name",
7712
- "description": "Human-readable project name.",
7713
- "required": true,
7714
- "type": "string",
7715
- "in": "body"
7716
- }]
7717
- },
7718
- "get-project": {
7719
- serviceClass: "Projects",
7720
- operationId: "getProject",
7721
- description: "Returns one project you are a member of, and your `role` in it. An id you are not a member of — including one that does not exist — responds `404`, not `403`: the API never confirms that an id exists elsewhere. `403` is reserved for the cases where there is nothing to hide: a project you *are* in, addressed with a credential scoped to a different one, or an action your role does not carry. There the message is what makes the failure fixable.",
7722
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8227
+ "list-orchestrations": {
8228
+ serviceClass: "Orchestrations",
8229
+ operationId: "listOrchestrations",
8230
+ description: "Returns orchestrations accessible to the caller.",
8231
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
7723
8232
  httpMethod: "get",
7724
8233
  pathParams: ["project_id"],
7725
- queryParams: [],
7726
- flags: [{
7727
- "name": "project_id",
7728
- "description": "Project public ID (proj_ prefix).",
7729
- "required": true,
7730
- "type": "string",
7731
- "in": "path"
7732
- }]
8234
+ queryParams: ["limit", "offset"],
8235
+ flags: [
8236
+ {
8237
+ "name": "project_id",
8238
+ "description": "Project public ID (proj_ prefix).",
8239
+ "required": true,
8240
+ "type": "string",
8241
+ "in": "path"
8242
+ },
8243
+ {
8244
+ "name": "limit",
8245
+ "description": "Maximum number of results to return",
8246
+ "required": false,
8247
+ "type": "integer",
8248
+ "in": "query"
8249
+ },
8250
+ {
8251
+ "name": "offset",
8252
+ "description": "Number of results to skip",
8253
+ "required": false,
8254
+ "type": "integer",
8255
+ "in": "query"
8256
+ }
8257
+ ]
7733
8258
  },
7734
- "update-project": {
7735
- serviceClass: "Projects",
7736
- operationId: "updateProject",
7737
- description: "Rename or archive a project, and/or change its content-retention settings (`trace_content_retention_days`, `trace_content_mode`). Archiving is reversible; resources are retained. Requires the `admin` role in the project (an `owner` has it too). The two retention controls answer different questions. The window bounds how long content *stays* — a daily sweep purges anything past it, leaving auditable skeletons behind. `trace_content_mode: none` means content is never *written*, which is the stronger guarantee: it cannot be missed by a sweep or survive in a backup.",
7738
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
7739
- httpMethod: "patch",
8259
+ "create-orchestration": {
8260
+ serviceClass: "Orchestrations",
8261
+ operationId: "createOrchestration",
8262
+ description: "Creates a new orchestration (pipeline) definition in the project.",
8263
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8264
+ httpMethod: "post",
7740
8265
  pathParams: ["project_id"],
7741
8266
  queryParams: [],
7742
8267
  flags: [
@@ -7749,63 +8274,117 @@ const routes = {
7749
8274
  },
7750
8275
  {
7751
8276
  "name": "name",
7752
- "description": "",
7753
- "required": false,
8277
+ "description": "Human-readable name.",
8278
+ "required": true,
7754
8279
  "type": "string",
7755
8280
  "in": "body"
7756
8281
  },
7757
8282
  {
7758
- "name": "status",
8283
+ "name": "description",
7759
8284
  "description": "",
7760
8285
  "required": false,
7761
8286
  "type": "string",
7762
8287
  "in": "body"
7763
8288
  },
7764
8289
  {
7765
- "name": "trace_content_retention_days",
7766
- "description": "Days of trace and generation content retention before the daily sweep purges it. Send `null` to disable retention (content is then kept until purged on demand). Omitting the field leaves the current window unchanged — `null` and absent are different instructions.\n",
8290
+ "name": "nodes",
8291
+ "description": "",
8292
+ "required": true,
8293
+ "type": "array",
8294
+ "in": "body"
8295
+ },
8296
+ {
8297
+ "name": "edges",
8298
+ "description": "",
8299
+ "required": true,
8300
+ "type": "array",
8301
+ "in": "body"
8302
+ },
8303
+ {
8304
+ "name": "state_schema",
8305
+ "description": "",
7767
8306
  "required": false,
7768
- "type": "integer",
8307
+ "type": "object",
7769
8308
  "in": "body"
7770
8309
  },
7771
8310
  {
7772
- "name": "trace_content_mode",
7773
- "description": "Set `none` for zero-retention: content is never written for any agent in this project. Tightening to `none` does not erase content already on disk — purge it explicitly, or set a retention window to have the sweep do it.\n",
8311
+ "name": "input_schema",
8312
+ "description": "",
8313
+ "required": false,
8314
+ "type": "object",
8315
+ "in": "body"
8316
+ },
8317
+ {
8318
+ "name": "version_label",
8319
+ "description": "Optional tag for the version this create archives, e.g. `initial`.",
7774
8320
  "required": false,
7775
8321
  "type": "string",
7776
8322
  "in": "body"
7777
8323
  }
7778
8324
  ]
7779
8325
  },
7780
- "delete-project": {
7781
- serviceClass: "Projects",
7782
- operationId: "deleteProject",
7783
- description: "Permanently deletes the project and its backing runtime project. Fails with 409 if the runtime project still has dependent resources remove them first, or pass `force=true` to delete the project and all its dependents (agents, providers, tools, sessions, generations, traces). Forcing is destructive and irreversible. Requires the `owner` role an `admin` runs the project day to day, but destroying it is the billing owner's call.",
7784
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
7785
- httpMethod: "delete",
8326
+ "validate-orchestration": {
8327
+ serviceClass: "Orchestrations",
8328
+ operationId: "validateOrchestration",
8329
+ description: "Statically validates an orchestration graph without persisting anything. Checks that every node has its required field, node ids are unique, edges reference existing nodes, the graph is acyclic (unless it contains a loop node), and every `input_mapping` `{\"var\": \"...\"}` reference resolves to a state key written by an upstream node or seeded by `input_schema`. Returns blocking `errors` and non-blocking `warnings` (e.g. a state key only written on a conditional branch). The same `errors` checks are enforced on create and update, which fail with `400` when any error is present.",
8330
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8331
+ httpMethod: "post",
7786
8332
  pathParams: ["project_id"],
7787
- queryParams: ["force"],
8333
+ queryParams: [],
8334
+ flags: [
8335
+ {
8336
+ "name": "project_id",
8337
+ "description": "Project public ID (proj_ prefix).",
8338
+ "required": true,
8339
+ "type": "string",
8340
+ "in": "path"
8341
+ },
8342
+ {
8343
+ "name": "nodes",
8344
+ "description": "",
8345
+ "required": false,
8346
+ "type": "array",
8347
+ "in": "body"
8348
+ },
8349
+ {
8350
+ "name": "edges",
8351
+ "description": "",
8352
+ "required": false,
8353
+ "type": "array",
8354
+ "in": "body"
8355
+ },
8356
+ {
8357
+ "name": "input_schema",
8358
+ "description": "Optional JSON Schema for run inputs; its top-level properties seed state.",
8359
+ "required": false,
8360
+ "type": "object",
8361
+ "in": "body"
8362
+ }
8363
+ ]
8364
+ },
8365
+ "get-queue-stats": {
8366
+ serviceClass: "Orchestrations",
8367
+ operationId: "getQueueStats",
8368
+ description: "Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`. A project-scoped caller sees only their own projects under `per_project`.",
8369
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8370
+ httpMethod: "get",
8371
+ pathParams: ["project_id"],
8372
+ queryParams: [],
7788
8373
  flags: [{
7789
8374
  "name": "project_id",
7790
8375
  "description": "Project public ID (proj_ prefix).",
7791
8376
  "required": true,
7792
8377
  "type": "string",
7793
8378
  "in": "path"
7794
- }, {
7795
- "name": "force",
7796
- "description": "When true, delete the resource together with its dependents instead of returning 409. Destructive and irreversible.\n",
7797
- "required": false,
7798
- "type": "boolean",
7799
- "in": "query"
7800
8379
  }]
7801
8380
  },
7802
- "list-project-members": {
7803
- serviceClass: "Projects",
7804
- operationId: "listProjectMembers",
7805
- description: "Lists who may act in the project, and with what role. Readable by every member, including a read-only `member`: who else is in the project is not a privileged fact, and hiding it makes \"why can that person see my agents?\" unanswerable. Read-only for now — adding and removing members arrives with the invitation flow, since an invitee may not have an account yet.",
7806
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8381
+ "get-orchestration": {
8382
+ serviceClass: "Orchestrations",
8383
+ operationId: "getOrchestration",
8384
+ description: "Returns the orchestration with nodes and edges.",
8385
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
7807
8386
  httpMethod: "get",
7808
- pathParams: ["project_id"],
8387
+ pathParams: ["project_id", "orchestration_id"],
7809
8388
  queryParams: [],
7810
8389
  flags: [{
7811
8390
  "name": "project_id",
@@ -7813,21 +8392,22 @@ const routes = {
7813
8392
  "required": true,
7814
8393
  "type": "string",
7815
8394
  "in": "path"
8395
+ }, {
8396
+ "name": "orchestration_id",
8397
+ "description": "Public ID of the orchestration (orch_...)",
8398
+ "required": true,
8399
+ "type": "string",
8400
+ "in": "path"
7816
8401
  }]
7817
8402
  },
7818
- "get-project-usage": {
7819
- serviceClass: "Projects",
7820
- operationId: "getProjectUsage",
7821
- description: "The per-project meter — the re-billing view (A11/C12/P3). Aggregates the project's usage over an optional [from, to] window, bucketed by a single dimension. Costs are the billing-grade cost_usd the runtime freezes at write time; null means nothing in the bucket was priced (never that it was free). Only managed providers are priced (on the runtime), so cost reflects managed usage; BYOK usage carries no LLM cost. Every bucket also carries components — the amounts actually measured. The token counts describe LLM usage alone, so that is where a storage, api_request or compute_execution bucket reports its real quantity instead of zeroed token fields.",
7822
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
7823
- httpMethod: "get",
7824
- pathParams: ["project_id"],
7825
- queryParams: [
7826
- "group_by",
7827
- "meter_type",
7828
- "from",
7829
- "to"
7830
- ],
8403
+ "update-orchestration": {
8404
+ serviceClass: "Orchestrations",
8405
+ operationId: "updateOrchestration",
8406
+ description: "Partially updates an orchestration definition.",
8407
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8408
+ httpMethod: "patch",
8409
+ pathParams: ["project_id", "orchestration_id"],
8410
+ queryParams: [],
7831
8411
  flags: [
7832
8412
  {
7833
8413
  "name": "project_id",
@@ -7837,42 +8417,92 @@ const routes = {
7837
8417
  "in": "path"
7838
8418
  },
7839
8419
  {
7840
- "name": "group_by",
7841
- "description": "Dimension to bucket by.",
7842
- "required": false,
8420
+ "name": "orchestration_id",
8421
+ "description": "Public ID of the orchestration (orch_...)",
8422
+ "required": true,
7843
8423
  "type": "string",
7844
- "in": "query"
8424
+ "in": "path"
7845
8425
  },
7846
8426
  {
7847
- "name": "meter_type",
7848
- "description": "Narrow the rollup to one meter type (llm_tokens, compute_execution, api_request, storage). Omit to include every meter. Useful with group_by=model, whose dimension otherwise mixes model ids with platform SKUs. An unrecognized value yields an empty rollup, not an error.\n",
8427
+ "name": "name",
8428
+ "description": "",
7849
8429
  "required": false,
7850
8430
  "type": "string",
7851
- "in": "query"
8431
+ "in": "body"
7852
8432
  },
7853
8433
  {
7854
- "name": "from",
7855
- "description": "Inclusive lower bound (ISO-8601) on event time. Omit for no lower bound.",
8434
+ "name": "description",
8435
+ "description": "",
7856
8436
  "required": false,
7857
8437
  "type": "string",
7858
- "in": "query"
8438
+ "in": "body"
7859
8439
  },
7860
8440
  {
7861
- "name": "to",
7862
- "description": "Inclusive upper bound (ISO-8601) on event time. Omit for no upper bound.",
8441
+ "name": "nodes",
8442
+ "description": "",
8443
+ "required": false,
8444
+ "type": "array",
8445
+ "in": "body"
8446
+ },
8447
+ {
8448
+ "name": "edges",
8449
+ "description": "",
8450
+ "required": false,
8451
+ "type": "array",
8452
+ "in": "body"
8453
+ },
8454
+ {
8455
+ "name": "state_schema",
8456
+ "description": "",
8457
+ "required": false,
8458
+ "type": "object",
8459
+ "in": "body"
8460
+ },
8461
+ {
8462
+ "name": "input_schema",
8463
+ "description": "",
8464
+ "required": false,
8465
+ "type": "object",
8466
+ "in": "body"
8467
+ },
8468
+ {
8469
+ "name": "version_label",
8470
+ "description": "Optional tag for the version this write archives, e.g. `pre-rewire`. Ignored when the write changes no graph field, since no version is archived.",
7863
8471
  "required": false,
7864
8472
  "type": "string",
7865
- "in": "query"
8473
+ "in": "body"
7866
8474
  }
7867
8475
  ]
7868
8476
  },
7869
- "list-secrets": {
7870
- serviceClass: "Secrets",
7871
- operationId: "listSecrets",
7872
- description: "Returns a list of secrets for a project",
7873
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
8477
+ "delete-orchestration": {
8478
+ serviceClass: "Orchestrations",
8479
+ operationId: "deleteOrchestration",
8480
+ description: "Deletes an orchestration definition and all its runs.",
8481
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8482
+ httpMethod: "delete",
8483
+ pathParams: ["project_id", "orchestration_id"],
8484
+ queryParams: [],
8485
+ flags: [{
8486
+ "name": "project_id",
8487
+ "description": "Project public ID (proj_ prefix).",
8488
+ "required": true,
8489
+ "type": "string",
8490
+ "in": "path"
8491
+ }, {
8492
+ "name": "orchestration_id",
8493
+ "description": "Public ID of the orchestration (orch_...)",
8494
+ "required": true,
8495
+ "type": "string",
8496
+ "in": "path"
8497
+ }]
8498
+ },
8499
+ "list-orchestration-versions": {
8500
+ serviceClass: "Orchestrations",
8501
+ operationId: "listOrchestrationVersions",
8502
+ description: "Returns the orchestration's archived graphs, newest first. A version is written on create and on every subsequent write that changes the graph (`nodes`, `edges`, `state_schema`, `input_schema`) — through the REST API or a formation apply alike. Metadata-only edits (name, description) do not archive a version. See [Versioning](/docs/modules/orchestrations#versioning).",
8503
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
7874
8504
  httpMethod: "get",
7875
- pathParams: ["project_id"],
8505
+ pathParams: ["project_id", "orchestration_id"],
7876
8506
  queryParams: ["limit", "offset"],
7877
8507
  flags: [
7878
8508
  {
@@ -7882,9 +8512,16 @@ const routes = {
7882
8512
  "type": "string",
7883
8513
  "in": "path"
7884
8514
  },
8515
+ {
8516
+ "name": "orchestration_id",
8517
+ "description": "Public ID of the orchestration (orch_...)",
8518
+ "required": true,
8519
+ "type": "string",
8520
+ "in": "path"
8521
+ },
7885
8522
  {
7886
8523
  "name": "limit",
7887
- "description": "Number of results per page",
8524
+ "description": "Maximum number of results to return",
7888
8525
  "required": false,
7889
8526
  "type": "integer",
7890
8527
  "in": "query"
@@ -7898,13 +8535,17 @@ const routes = {
7898
8535
  }
7899
8536
  ]
7900
8537
  },
7901
- "create-secret": {
7902
- serviceClass: "Secrets",
7903
- operationId: "createSecret",
7904
- description: "Creates a new encrypted secret in a project",
7905
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
7906
- httpMethod: "post",
7907
- pathParams: ["project_id"],
8538
+ "get-orchestration-version": {
8539
+ serviceClass: "Orchestrations",
8540
+ operationId: "getOrchestrationVersion",
8541
+ description: "Returns the exact graph a given version describes. Every run records the version it started on in `orchestration_version` and executes that graph for its whole life, so this is how you read the topology a run actually took — including a run whose orchestration has been rewired since.",
8542
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8543
+ httpMethod: "get",
8544
+ pathParams: [
8545
+ "project_id",
8546
+ "orchestration_id",
8547
+ "version"
8548
+ ],
7908
8549
  queryParams: [],
7909
8550
  flags: [
7910
8551
  {
@@ -7915,50 +8556,32 @@ const routes = {
7915
8556
  "in": "path"
7916
8557
  },
7917
8558
  {
7918
- "name": "name",
7919
- "description": "Secret name",
8559
+ "name": "orchestration_id",
8560
+ "description": "Public ID of the orchestration (orch_...)",
7920
8561
  "required": true,
7921
8562
  "type": "string",
7922
- "in": "body"
8563
+ "in": "path"
7923
8564
  },
7924
8565
  {
7925
- "name": "value",
7926
- "description": "Secret value (will be encrypted)",
8566
+ "name": "version",
8567
+ "description": "The archived version number",
7927
8568
  "required": true,
7928
- "type": "string",
7929
- "in": "body"
8569
+ "type": "integer",
8570
+ "in": "path"
7930
8571
  }
7931
8572
  ]
7932
8573
  },
7933
- "get-secret": {
7934
- serviceClass: "Secrets",
7935
- operationId: "getSecret",
7936
- description: "Returns a specific secret",
7937
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
7938
- httpMethod: "get",
7939
- pathParams: ["project_id", "secret_id"],
7940
- queryParams: [],
7941
- flags: [{
7942
- "name": "project_id",
7943
- "description": "Project public ID (proj_ prefix).",
7944
- "required": true,
7945
- "type": "string",
7946
- "in": "path"
7947
- }, {
7948
- "name": "secret_id",
7949
- "description": "Secret ID",
7950
- "required": true,
7951
- "type": "string",
7952
- "in": "path"
7953
- }]
7954
- },
7955
- "update-secret": {
7956
- serviceClass: "Secrets",
7957
- operationId: "updateSecret",
7958
- description: "Updates a secret's name and/or value",
7959
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
7960
- httpMethod: "patch",
7961
- pathParams: ["project_id", "secret_id"],
8574
+ "restore-orchestration-version": {
8575
+ serviceClass: "Orchestrations",
8576
+ operationId: "restoreOrchestrationVersion",
8577
+ description: "Writes an archived version's graph back as the orchestration's live definition, which archives it again as a **new** version rather than rewinding the counter — so a run pinned to any version in between still resolves the graph it started on. The restore runs through the ordinary update path, so the archived graph goes through the same static validation as an authored one. Node resource references (`agent_id`, `tool_id`, `orchestration_id`) resolve when a run reaches the node, so a target deleted since the snapshot was taken restores cleanly and surfaces as a failed run rather than a `400`. Restoring the graph the orchestration already holds is a no-op and archives nothing. Runs already in flight are unaffected either way — a restore is an ordinary edit, and pinning is what keeps it from reaching them.",
8578
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8579
+ httpMethod: "post",
8580
+ pathParams: [
8581
+ "project_id",
8582
+ "orchestration_id",
8583
+ "version"
8584
+ ],
7962
8585
  queryParams: [],
7963
8586
  flags: [
7964
8587
  {
@@ -7969,61 +8592,37 @@ const routes = {
7969
8592
  "in": "path"
7970
8593
  },
7971
8594
  {
7972
- "name": "secret_id",
7973
- "description": "Secret ID",
8595
+ "name": "orchestration_id",
8596
+ "description": "Public ID of the orchestration (orch_...)",
7974
8597
  "required": true,
7975
8598
  "type": "string",
7976
8599
  "in": "path"
7977
8600
  },
7978
8601
  {
7979
- "name": "name",
7980
- "description": "New secret name",
7981
- "required": false,
7982
- "type": "string",
7983
- "in": "body"
8602
+ "name": "version",
8603
+ "description": "The archived version number",
8604
+ "required": true,
8605
+ "type": "integer",
8606
+ "in": "path"
7984
8607
  },
7985
8608
  {
7986
- "name": "value",
7987
- "description": "New secret value",
8609
+ "name": "label",
8610
+ "description": "Optional tag for the version the restore creates. Defaults to `restored from v<version>`.",
7988
8611
  "required": false,
7989
8612
  "type": "string",
7990
8613
  "in": "body"
7991
8614
  }
7992
8615
  ]
7993
8616
  },
7994
- "delete-secret": {
7995
- serviceClass: "Secrets",
7996
- operationId: "deleteSecret",
7997
- description: "Deletes a secret",
7998
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
7999
- httpMethod: "delete",
8000
- pathParams: ["project_id", "secret_id"],
8001
- queryParams: [],
8002
- flags: [{
8003
- "name": "project_id",
8004
- "description": "Project public ID (proj_ prefix).",
8005
- "required": true,
8006
- "type": "string",
8007
- "in": "path"
8008
- }, {
8009
- "name": "secret_id",
8010
- "description": "Secret ID",
8011
- "required": true,
8012
- "type": "string",
8013
- "in": "path"
8014
- }]
8015
- },
8016
- "list-sessions": {
8017
- serviceClass: "Sessions",
8018
- operationId: "listSessions",
8019
- description: "Returns sessions the caller can access, optionally filtered by agent, actor and status.",
8020
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8617
+ "list-orchestration-runs": {
8618
+ serviceClass: "Orchestrations",
8619
+ operationId: "listOrchestrationRuns",
8620
+ description: "Returns orchestration runs the caller can access, optionally filtered by orchestration.",
8621
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8021
8622
  httpMethod: "get",
8022
8623
  pathParams: ["project_id"],
8023
8624
  queryParams: [
8024
- "agent_id",
8025
- "actor_id",
8026
- "status",
8625
+ "orchestration_id",
8027
8626
  "limit",
8028
8627
  "offset"
8029
8628
  ],
@@ -8036,47 +8635,33 @@ const routes = {
8036
8635
  "in": "path"
8037
8636
  },
8038
8637
  {
8039
- "name": "agent_id",
8040
- "description": "Filter by agent public ID",
8041
- "required": false,
8042
- "type": "string",
8043
- "in": "query"
8044
- },
8045
- {
8046
- "name": "actor_id",
8047
- "description": "Filter by actor public ID",
8048
- "required": false,
8049
- "type": "string",
8050
- "in": "query"
8051
- },
8052
- {
8053
- "name": "status",
8054
- "description": "Filter by session status (open, closed, or expired)",
8638
+ "name": "orchestration_id",
8639
+ "description": "Filter by orchestration public ID (orch_...)",
8055
8640
  "required": false,
8056
8641
  "type": "string",
8057
8642
  "in": "query"
8058
8643
  },
8059
8644
  {
8060
8645
  "name": "limit",
8061
- "description": "",
8646
+ "description": "Maximum number of results to return",
8062
8647
  "required": false,
8063
8648
  "type": "integer",
8064
8649
  "in": "query"
8065
8650
  },
8066
8651
  {
8067
8652
  "name": "offset",
8068
- "description": "",
8653
+ "description": "Number of results to skip",
8069
8654
  "required": false,
8070
8655
  "type": "integer",
8071
8656
  "in": "query"
8072
8657
  }
8073
8658
  ]
8074
8659
  },
8075
- "create-session": {
8076
- serviceClass: "Sessions",
8077
- operationId: "createSession",
8078
- description: "Creates a new session for the specified agent, along with the underlying conversation, so the caller only needs this single call to start interacting with the agent. No actor is created: pass `actor_id` to attach an existing actor as the session's end user. When it is omitted the session has no actor, and generations in it carry no end-user attribution they are not billed to an actor in the usage meter and they match no `actor`-scoped quota.",
8079
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8660
+ "start-orchestration-run": {
8661
+ serviceClass: "Orchestrations",
8662
+ operationId: "startOrchestrationRun",
8663
+ description: "Creates a new run for the orchestration named by orchestration_id. By default the run executes durably in the background: the response returns immediately with status \"queued\" (a worker then claims it and moves it to \"running\") and progress is observed via get-orchestration-run or run lifecycle webhook events (orchestration_runs.started/awaiting_input/succeeded/failed). Delay and poll waits park the run as \"sleeping\" and are woken by a background scheduler, surviving restarts. Pass wait=true to block until the run reaches a terminal or awaiting_input state.",
8664
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8080
8665
  httpMethod: "post",
8081
8666
  pathParams: ["project_id"],
8082
8667
  queryParams: [],
@@ -8089,63 +8674,42 @@ const routes = {
8089
8674
  "in": "path"
8090
8675
  },
8091
8676
  {
8092
- "name": "agent_id",
8093
- "description": "Agent this session belongs to",
8677
+ "name": "orchestration_id",
8678
+ "description": "Orchestration to run (orch_...).",
8094
8679
  "required": true,
8095
8680
  "type": "string",
8096
8681
  "in": "body"
8097
8682
  },
8098
8683
  {
8099
- "name": "name",
8100
- "description": "Optional session name",
8101
- "required": false,
8102
- "type": "string",
8103
- "in": "body"
8104
- },
8105
- {
8106
- "name": "actor_id",
8107
- "description": "Optional public ID of an existing actor to use as the user actor. Actors are created separately (POST /actors); this field only links one. Omit it and the session has no end user, so its generations match no actor-scoped quota.\n",
8108
- "required": false,
8109
- "type": "string",
8110
- "in": "body"
8111
- },
8112
- {
8113
- "name": "auto_generate",
8114
- "description": "When true, automatically triggers generation after each user message.",
8684
+ "name": "input",
8685
+ "description": "Initial state for the run (merged with orchestration defaults).",
8115
8686
  "required": false,
8116
- "type": "boolean",
8687
+ "type": "object",
8117
8688
  "in": "body"
8118
8689
  },
8119
8690
  {
8120
8691
  "name": "tool_context",
8121
- "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this session. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim no character is re-cased. Keys are never case-converted they round-trip exactly as sent. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
8692
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call made by an agent node of this run — including the agents of any child run a `loop` or `sub_orchestration` node starts. The header name is `X-Naturali-Context-` plus the key verbatim; no character is re-cased.\n\nThe bag is stored on the run and re-read on every step, so it survives an `awaiting_input` pause, a `sleeping` wait, a background worker drive and a crash redrive. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with `400 INVALID_TOOL_CONTEXT_KEY` and no run is created.\n\nThe reserved identity keys (`sessionId`, `actorId`, `actorExternalId`) are stripped at generation time — a caller cannot address them from here.",
8122
8693
  "required": false,
8123
8694
  "type": "object",
8124
8695
  "in": "body"
8125
8696
  },
8126
8697
  {
8127
- "name": "inactivity_ttl_seconds",
8128
- "description": "Number of seconds of inactivity after which the session expires. 0 means the session never expires.",
8129
- "required": false,
8130
- "type": "integer",
8131
- "in": "body"
8132
- },
8133
- {
8134
- "name": "message_delay_seconds",
8135
- "description": "Number of seconds to wait after the last user message before sending to the LLM. Acts as a debounce: each new message resets the timer. null or absent means no delay (immediate processing).\n",
8698
+ "name": "wait",
8699
+ "description": "When true, block until the run reaches a terminal (succeeded/failed) or awaiting_input state and return the settled run. When false (default), return immediately with status \"queued\" and execute the run in the background.",
8136
8700
  "required": false,
8137
- "type": "integer",
8701
+ "type": "boolean",
8138
8702
  "in": "body"
8139
8703
  }
8140
8704
  ]
8141
8705
  },
8142
- "get-session": {
8143
- serviceClass: "Sessions",
8144
- operationId: "getSession",
8145
- description: "Returns details of a single session.",
8146
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8147
- httpMethod: "get",
8148
- pathParams: ["project_id", "session_id"],
8706
+ "cancel-orchestration-run": {
8707
+ serviceClass: "Orchestrations",
8708
+ operationId: "cancelOrchestrationRun",
8709
+ description: "Cancels a run that has not yet reached a terminal state.",
8710
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8711
+ httpMethod: "post",
8712
+ pathParams: ["project_id", "orchestration_run_id"],
8149
8713
  queryParams: [],
8150
8714
  flags: [{
8151
8715
  "name": "project_id",
@@ -8154,20 +8718,20 @@ const routes = {
8154
8718
  "type": "string",
8155
8719
  "in": "path"
8156
8720
  }, {
8157
- "name": "session_id",
8158
- "description": "Session public ID",
8721
+ "name": "orchestration_run_id",
8722
+ "description": "Public ID of the run (run_...)",
8159
8723
  "required": true,
8160
8724
  "type": "string",
8161
8725
  "in": "path"
8162
8726
  }]
8163
8727
  },
8164
- "update-session": {
8165
- serviceClass: "Sessions",
8166
- operationId: "updateSession",
8167
- description: "Updates the session name and/or status.",
8168
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8169
- httpMethod: "patch",
8170
- pathParams: ["project_id", "session_id"],
8728
+ "submit-human-input": {
8729
+ serviceClass: "Orchestrations",
8730
+ operationId: "submitHumanInput",
8731
+ description: "Provides human input to a run that is awaiting_input at a human node.",
8732
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8733
+ httpMethod: "post",
8734
+ pathParams: ["project_id", "orchestration_run_id"],
8171
8735
  queryParams: [],
8172
8736
  flags: [
8173
8737
  {
@@ -8178,63 +8742,35 @@ const routes = {
8178
8742
  "in": "path"
8179
8743
  },
8180
8744
  {
8181
- "name": "session_id",
8182
- "description": "Session public ID",
8745
+ "name": "orchestration_run_id",
8746
+ "description": "Public ID of the run (run_...)",
8183
8747
  "required": true,
8184
8748
  "type": "string",
8185
8749
  "in": "path"
8186
8750
  },
8187
8751
  {
8188
- "name": "name",
8189
- "description": "Session name (set to null to clear)",
8190
- "required": false,
8191
- "type": "string",
8192
- "in": "body"
8193
- },
8194
- {
8195
- "name": "status",
8196
- "description": "Session status",
8197
- "required": false,
8752
+ "name": "node_id",
8753
+ "description": "ID of the human node to satisfy.",
8754
+ "required": true,
8198
8755
  "type": "string",
8199
8756
  "in": "body"
8200
8757
  },
8201
8758
  {
8202
- "name": "auto_generate",
8203
- "description": "Enable or disable automatic generation after user messages.",
8204
- "required": false,
8205
- "type": "boolean",
8206
- "in": "body"
8207
- },
8208
- {
8209
- "name": "tool_context",
8210
- "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this session. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
8759
+ "name": "output",
8760
+ "description": "Output/response provided by the human reviewer.",
8211
8761
  "required": false,
8212
8762
  "type": "object",
8213
8763
  "in": "body"
8214
- },
8215
- {
8216
- "name": "inactivity_ttl_seconds",
8217
- "description": "Number of seconds of inactivity after which the session expires. 0 means the session never expires. Updates the stored TTL; the inactivity clock continues from the last activity timestamp.\n",
8218
- "required": false,
8219
- "type": "integer",
8220
- "in": "body"
8221
- },
8222
- {
8223
- "name": "message_delay_seconds",
8224
- "description": "Number of seconds to wait after the last user message before sending to the LLM. Acts as a debounce: each new message resets the timer. Set to null to disable the delay.\n",
8225
- "required": false,
8226
- "type": "integer",
8227
- "in": "body"
8228
8764
  }
8229
8765
  ]
8230
8766
  },
8231
- "delete-session": {
8232
- serviceClass: "Sessions",
8233
- operationId: "deleteSession",
8234
- description: "Deletes the session and its underlying conversation and messages. The session's actor is not deleted. Generations and traces produced by the session are not deleted either, since they are not linked to the session or conversation.",
8235
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8236
- httpMethod: "delete",
8237
- pathParams: ["project_id", "session_id"],
8767
+ "resume-orchestration-run": {
8768
+ serviceClass: "Orchestrations",
8769
+ operationId: "resumeOrchestrationRun",
8770
+ description: "Re-drives an awaiting_input orchestration run from its last checkpoint. This does not satisfy the pause itself it carries no node_id or payload, so a run parked on a human or webhook-receive node re-parks on the same node. Use submit-human-input to supply the awaited payload and advance the run.",
8771
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8772
+ httpMethod: "post",
8773
+ pathParams: ["project_id", "orchestration_run_id"],
8238
8774
  queryParams: [],
8239
8775
  flags: [{
8240
8776
  "name": "project_id",
@@ -8243,20 +8779,96 @@ const routes = {
8243
8779
  "type": "string",
8244
8780
  "in": "path"
8245
8781
  }, {
8246
- "name": "session_id",
8247
- "description": "Session public ID",
8782
+ "name": "orchestration_run_id",
8783
+ "description": "Public ID of the run (run_...)",
8248
8784
  "required": true,
8249
8785
  "type": "string",
8250
8786
  "in": "path"
8251
8787
  }]
8252
8788
  },
8253
- "add-session-message": {
8254
- serviceClass: "Sessions",
8255
- operationId: "addSessionMessage",
8256
- description: "Saves a user message to the session. When autoGenerate is enabled on the session and no generation is currently in progress, generation is triggered automatically and the response mirrors GenerateSessionResponse. Otherwise returns the saved user message.",
8257
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8789
+ "get-orchestration-run": {
8790
+ serviceClass: "Orchestrations",
8791
+ operationId: "getOrchestrationRun",
8792
+ description: "Returns the status, state, and artifacts of a specific run.",
8793
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
8794
+ httpMethod: "get",
8795
+ pathParams: ["project_id", "orchestration_run_id"],
8796
+ queryParams: [],
8797
+ flags: [{
8798
+ "name": "project_id",
8799
+ "description": "Project public ID (proj_ prefix).",
8800
+ "required": true,
8801
+ "type": "string",
8802
+ "in": "path"
8803
+ }, {
8804
+ "name": "orchestration_run_id",
8805
+ "description": "Public ID of the run (run_...)",
8806
+ "required": true,
8807
+ "type": "string",
8808
+ "in": "path"
8809
+ }]
8810
+ },
8811
+ "list-projects": {
8812
+ serviceClass: "Projects",
8813
+ operationId: "listProjects",
8814
+ description: "Lists the projects the caller is a member of. A project-scoped API key lists only its own project.",
8815
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8816
+ httpMethod: "get",
8817
+ pathParams: [],
8818
+ queryParams: ["limit", "cursor"],
8819
+ flags: [{
8820
+ "name": "limit",
8821
+ "description": "Maximum items per page — an integer from 1 to 100 (default 20).",
8822
+ "required": false,
8823
+ "type": "integer",
8824
+ "in": "query"
8825
+ }, {
8826
+ "name": "cursor",
8827
+ "description": "Opaque pagination cursor from a previous response's next_cursor.",
8828
+ "required": false,
8829
+ "type": "string",
8830
+ "in": "query"
8831
+ }]
8832
+ },
8833
+ "create-project": {
8834
+ serviceClass: "Projects",
8835
+ operationId: "createProject",
8836
+ description: "Creates a project (one per client or per environment).",
8837
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8258
8838
  httpMethod: "post",
8259
- pathParams: ["project_id", "session_id"],
8839
+ pathParams: [],
8840
+ queryParams: [],
8841
+ flags: [{
8842
+ "name": "name",
8843
+ "description": "Human-readable project name.",
8844
+ "required": true,
8845
+ "type": "string",
8846
+ "in": "body"
8847
+ }]
8848
+ },
8849
+ "get-project": {
8850
+ serviceClass: "Projects",
8851
+ operationId: "getProject",
8852
+ description: "Returns one project you are a member of, and your `role` in it. An id you are not a member of — including one that does not exist — responds `404`, not `403`: the API never confirms that an id exists elsewhere. `403` is reserved for the cases where there is nothing to hide: a project you *are* in, addressed with a credential scoped to a different one, or an action your role does not carry. There the message is what makes the failure fixable.",
8853
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8854
+ httpMethod: "get",
8855
+ pathParams: ["project_id"],
8856
+ queryParams: [],
8857
+ flags: [{
8858
+ "name": "project_id",
8859
+ "description": "Project public ID (proj_ prefix).",
8860
+ "required": true,
8861
+ "type": "string",
8862
+ "in": "path"
8863
+ }]
8864
+ },
8865
+ "update-project": {
8866
+ serviceClass: "Projects",
8867
+ operationId: "updateProject",
8868
+ description: "Rename or archive a project, and/or change its content-retention settings (`trace_content_retention_days`, `trace_content_mode`). Archiving is reversible; resources are retained. Requires the `admin` role in the project (an `owner` has it too). The two retention controls answer different questions. The window bounds how long content *stays* — a daily sweep purges anything past it, leaving auditable skeletons behind. `trace_content_mode: none` means content is never *written*, which is the stronger guarantee: it cannot be missed by a sweep or survive in a backup.",
8869
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8870
+ httpMethod: "patch",
8871
+ pathParams: ["project_id"],
8260
8872
  queryParams: [],
8261
8873
  flags: [
8262
8874
  {
@@ -8267,95 +8879,1266 @@ const routes = {
8267
8879
  "in": "path"
8268
8880
  },
8269
8881
  {
8270
- "name": "session_id",
8271
- "description": "Session public ID",
8272
- "required": true,
8273
- "type": "string",
8274
- "in": "path"
8275
- },
8276
- {
8277
- "name": "message",
8278
- "description": "User message text",
8882
+ "name": "name",
8883
+ "description": "",
8279
8884
  "required": false,
8280
8885
  "type": "string",
8281
8886
  "in": "body"
8282
8887
  },
8283
8888
  {
8284
- "name": "tool_context",
8285
- "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this generation. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
8889
+ "name": "status",
8890
+ "description": "",
8286
8891
  "required": false,
8287
- "type": "object",
8892
+ "type": "string",
8288
8893
  "in": "body"
8289
8894
  },
8290
8895
  {
8291
- "name": "idempotency_key",
8292
- "description": "Optional deduplication key scoped to this session. If a message with the same key already exists in the session, the original message is returned with HTTP 200 and no new message or generation is triggered.\n",
8896
+ "name": "trace_content_retention_days",
8897
+ "description": "Days of trace and generation content retention before the daily sweep purges it. Send `null` to disable retention (content is then kept until purged on demand). Omitting the field leaves the current window unchanged `null` and absent are different instructions.\n",
8293
8898
  "required": false,
8294
- "type": "string",
8899
+ "type": "integer",
8295
8900
  "in": "body"
8296
8901
  },
8297
8902
  {
8298
- "name": "document_id",
8299
- "description": "Public ID of a document used as the user message content.",
8903
+ "name": "trace_content_mode",
8904
+ "description": "Set `none` for zero-retention: content is never written for any agent in this project. Tightening to `none` does not erase content already on disk — purge it explicitly, or set a retention window to have the sweep do it.\n",
8300
8905
  "required": false,
8301
8906
  "type": "string",
8302
8907
  "in": "body"
8303
8908
  }
8304
8909
  ]
8305
8910
  },
8306
- "generate-session-response": {
8307
- serviceClass: "Sessions",
8308
- operationId: "generateSessionResponse",
8309
- description: "Triggers the agent to generate a response based on the current conversation. Background by default: returns `202 Accepted` immediately while the generation runs. Pass ?wait=true to block and receive the assistant reply (or a requires_action status if the agent needs client tool outputs) in the response.",
8310
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8311
- httpMethod: "post",
8312
- pathParams: ["project_id", "session_id"],
8313
- queryParams: ["wait"],
8314
- flags: [
8315
- {
8316
- "name": "project_id",
8317
- "description": "Project public ID (proj_ prefix).",
8318
- "required": true,
8911
+ "delete-project": {
8912
+ serviceClass: "Projects",
8913
+ operationId: "deleteProject",
8914
+ description: "Permanently deletes the project and its backing runtime project. Fails with 409 if the runtime project still has dependent resources remove them first, or pass `force=true` to delete the project and all its dependents (agents, providers, tools, sessions, generations, traces). Forcing is destructive and irreversible. Requires the `owner` role an `admin` runs the project day to day, but destroying it is the billing owner's call.",
8915
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8916
+ httpMethod: "delete",
8917
+ pathParams: ["project_id"],
8918
+ queryParams: ["force"],
8919
+ flags: [{
8920
+ "name": "project_id",
8921
+ "description": "Project public ID (proj_ prefix).",
8922
+ "required": true,
8923
+ "type": "string",
8924
+ "in": "path"
8925
+ }, {
8926
+ "name": "force",
8927
+ "description": "When true, delete the resource together with its dependents instead of returning 409. Destructive and irreversible.\n",
8928
+ "required": false,
8929
+ "type": "boolean",
8930
+ "in": "query"
8931
+ }]
8932
+ },
8933
+ "list-project-members": {
8934
+ serviceClass: "Projects",
8935
+ operationId: "listProjectMembers",
8936
+ description: "Lists who may act in the project, and with what role. Readable by every member, including a read-only `member`: who else is in the project is not a privileged fact, and hiding it makes \"why can that person see my agents?\" unanswerable. Read-only for now — adding and removing members arrives with the invitation flow, since an invitee may not have an account yet.",
8937
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8938
+ httpMethod: "get",
8939
+ pathParams: ["project_id"],
8940
+ queryParams: [],
8941
+ flags: [{
8942
+ "name": "project_id",
8943
+ "description": "Project public ID (proj_ prefix).",
8944
+ "required": true,
8945
+ "type": "string",
8946
+ "in": "path"
8947
+ }]
8948
+ },
8949
+ "get-project-usage": {
8950
+ serviceClass: "Projects",
8951
+ operationId: "getProjectUsage",
8952
+ description: "The per-project meter — the re-billing view (A11/C12/P3). Aggregates the project's usage over an optional [from, to] window, bucketed by a single dimension. Costs are the billing-grade cost_usd the runtime freezes at write time; null means nothing in the bucket was priced (never that it was free). Only managed providers are priced (on the runtime), so cost reflects managed usage; BYOK usage carries no LLM cost. Every bucket also carries components — the amounts actually measured. The token counts describe LLM usage alone, so that is where a storage, api_request or compute_execution bucket reports its real quantity instead of zeroed token fields.",
8953
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/projects",
8954
+ httpMethod: "get",
8955
+ pathParams: ["project_id"],
8956
+ queryParams: [
8957
+ "group_by",
8958
+ "meter_type",
8959
+ "from",
8960
+ "to"
8961
+ ],
8962
+ flags: [
8963
+ {
8964
+ "name": "project_id",
8965
+ "description": "Project public ID (proj_ prefix).",
8966
+ "required": true,
8967
+ "type": "string",
8968
+ "in": "path"
8969
+ },
8970
+ {
8971
+ "name": "group_by",
8972
+ "description": "Dimension to bucket by.",
8973
+ "required": false,
8974
+ "type": "string",
8975
+ "in": "query"
8976
+ },
8977
+ {
8978
+ "name": "meter_type",
8979
+ "description": "Narrow the rollup to one meter type (llm_tokens, compute_execution, api_request, storage). Omit to include every meter. Useful with group_by=model, whose dimension otherwise mixes model ids with platform SKUs. An unrecognized value yields an empty rollup, not an error.\n",
8980
+ "required": false,
8981
+ "type": "string",
8982
+ "in": "query"
8983
+ },
8984
+ {
8985
+ "name": "from",
8986
+ "description": "Inclusive lower bound (ISO-8601) on event time. Omit for no lower bound.",
8987
+ "required": false,
8988
+ "type": "string",
8989
+ "in": "query"
8990
+ },
8991
+ {
8992
+ "name": "to",
8993
+ "description": "Inclusive upper bound (ISO-8601) on event time. Omit for no upper bound.",
8994
+ "required": false,
8995
+ "type": "string",
8996
+ "in": "query"
8997
+ }
8998
+ ]
8999
+ },
9000
+ "list-secrets": {
9001
+ serviceClass: "Secrets",
9002
+ operationId: "listSecrets",
9003
+ description: "Returns a list of secrets for a project",
9004
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
9005
+ httpMethod: "get",
9006
+ pathParams: ["project_id"],
9007
+ queryParams: ["limit", "offset"],
9008
+ flags: [
9009
+ {
9010
+ "name": "project_id",
9011
+ "description": "Project public ID (proj_ prefix).",
9012
+ "required": true,
9013
+ "type": "string",
9014
+ "in": "path"
9015
+ },
9016
+ {
9017
+ "name": "limit",
9018
+ "description": "Number of results per page",
9019
+ "required": false,
9020
+ "type": "integer",
9021
+ "in": "query"
9022
+ },
9023
+ {
9024
+ "name": "offset",
9025
+ "description": "Number of results to skip",
9026
+ "required": false,
9027
+ "type": "integer",
9028
+ "in": "query"
9029
+ }
9030
+ ]
9031
+ },
9032
+ "create-secret": {
9033
+ serviceClass: "Secrets",
9034
+ operationId: "createSecret",
9035
+ description: "Creates a new encrypted secret in a project",
9036
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
9037
+ httpMethod: "post",
9038
+ pathParams: ["project_id"],
9039
+ queryParams: [],
9040
+ flags: [
9041
+ {
9042
+ "name": "project_id",
9043
+ "description": "Project public ID (proj_ prefix).",
9044
+ "required": true,
9045
+ "type": "string",
9046
+ "in": "path"
9047
+ },
9048
+ {
9049
+ "name": "name",
9050
+ "description": "Secret name",
9051
+ "required": true,
9052
+ "type": "string",
9053
+ "in": "body"
9054
+ },
9055
+ {
9056
+ "name": "value",
9057
+ "description": "Secret value (will be encrypted)",
9058
+ "required": true,
9059
+ "type": "string",
9060
+ "in": "body"
9061
+ }
9062
+ ]
9063
+ },
9064
+ "get-secret": {
9065
+ serviceClass: "Secrets",
9066
+ operationId: "getSecret",
9067
+ description: "Returns a specific secret",
9068
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
9069
+ httpMethod: "get",
9070
+ pathParams: ["project_id", "secret_id"],
9071
+ queryParams: [],
9072
+ flags: [{
9073
+ "name": "project_id",
9074
+ "description": "Project public ID (proj_ prefix).",
9075
+ "required": true,
9076
+ "type": "string",
9077
+ "in": "path"
9078
+ }, {
9079
+ "name": "secret_id",
9080
+ "description": "Secret ID",
9081
+ "required": true,
9082
+ "type": "string",
9083
+ "in": "path"
9084
+ }]
9085
+ },
9086
+ "update-secret": {
9087
+ serviceClass: "Secrets",
9088
+ operationId: "updateSecret",
9089
+ description: "Updates a secret's name and/or value",
9090
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
9091
+ httpMethod: "patch",
9092
+ pathParams: ["project_id", "secret_id"],
9093
+ queryParams: [],
9094
+ flags: [
9095
+ {
9096
+ "name": "project_id",
9097
+ "description": "Project public ID (proj_ prefix).",
9098
+ "required": true,
9099
+ "type": "string",
9100
+ "in": "path"
9101
+ },
9102
+ {
9103
+ "name": "secret_id",
9104
+ "description": "Secret ID",
9105
+ "required": true,
9106
+ "type": "string",
9107
+ "in": "path"
9108
+ },
9109
+ {
9110
+ "name": "name",
9111
+ "description": "New secret name",
9112
+ "required": false,
9113
+ "type": "string",
9114
+ "in": "body"
9115
+ },
9116
+ {
9117
+ "name": "value",
9118
+ "description": "New secret value",
9119
+ "required": false,
9120
+ "type": "string",
9121
+ "in": "body"
9122
+ }
9123
+ ]
9124
+ },
9125
+ "delete-secret": {
9126
+ serviceClass: "Secrets",
9127
+ operationId: "deleteSecret",
9128
+ description: "Deletes a secret",
9129
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/secrets",
9130
+ httpMethod: "delete",
9131
+ pathParams: ["project_id", "secret_id"],
9132
+ queryParams: [],
9133
+ flags: [{
9134
+ "name": "project_id",
9135
+ "description": "Project public ID (proj_ prefix).",
9136
+ "required": true,
9137
+ "type": "string",
9138
+ "in": "path"
9139
+ }, {
9140
+ "name": "secret_id",
9141
+ "description": "Secret ID",
9142
+ "required": true,
9143
+ "type": "string",
9144
+ "in": "path"
9145
+ }]
9146
+ },
9147
+ "list-sessions": {
9148
+ serviceClass: "Sessions",
9149
+ operationId: "listSessions",
9150
+ description: "Returns sessions the caller can access, optionally filtered by agent, actor and status.",
9151
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9152
+ httpMethod: "get",
9153
+ pathParams: ["project_id"],
9154
+ queryParams: [
9155
+ "agent_id",
9156
+ "actor_id",
9157
+ "status",
9158
+ "limit",
9159
+ "offset"
9160
+ ],
9161
+ flags: [
9162
+ {
9163
+ "name": "project_id",
9164
+ "description": "Project public ID (proj_ prefix).",
9165
+ "required": true,
9166
+ "type": "string",
9167
+ "in": "path"
9168
+ },
9169
+ {
9170
+ "name": "agent_id",
9171
+ "description": "Filter by agent public ID",
9172
+ "required": false,
9173
+ "type": "string",
9174
+ "in": "query"
9175
+ },
9176
+ {
9177
+ "name": "actor_id",
9178
+ "description": "Filter by actor public ID",
9179
+ "required": false,
9180
+ "type": "string",
9181
+ "in": "query"
9182
+ },
9183
+ {
9184
+ "name": "status",
9185
+ "description": "Filter by session status (open, closed, or expired)",
9186
+ "required": false,
9187
+ "type": "string",
9188
+ "in": "query"
9189
+ },
9190
+ {
9191
+ "name": "limit",
9192
+ "description": "",
9193
+ "required": false,
9194
+ "type": "integer",
9195
+ "in": "query"
9196
+ },
9197
+ {
9198
+ "name": "offset",
9199
+ "description": "",
9200
+ "required": false,
9201
+ "type": "integer",
9202
+ "in": "query"
9203
+ }
9204
+ ]
9205
+ },
9206
+ "create-session": {
9207
+ serviceClass: "Sessions",
9208
+ operationId: "createSession",
9209
+ description: "Creates a new session for the specified agent, along with the underlying conversation, so the caller only needs this single call to start interacting with the agent. No actor is created: pass `actor_id` to attach an existing actor as the session's end user. When it is omitted the session has no actor, and generations in it carry no end-user attribution — they are not billed to an actor in the usage meter and they match no `actor`-scoped quota.",
9210
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9211
+ httpMethod: "post",
9212
+ pathParams: ["project_id"],
9213
+ queryParams: [],
9214
+ flags: [
9215
+ {
9216
+ "name": "project_id",
9217
+ "description": "Project public ID (proj_ prefix).",
9218
+ "required": true,
9219
+ "type": "string",
9220
+ "in": "path"
9221
+ },
9222
+ {
9223
+ "name": "agent_id",
9224
+ "description": "Agent this session belongs to",
9225
+ "required": true,
9226
+ "type": "string",
9227
+ "in": "body"
9228
+ },
9229
+ {
9230
+ "name": "name",
9231
+ "description": "Optional session name",
9232
+ "required": false,
9233
+ "type": "string",
9234
+ "in": "body"
9235
+ },
9236
+ {
9237
+ "name": "actor_id",
9238
+ "description": "Optional public ID of an existing actor to use as the user actor. Actors are created separately (POST /actors); this field only links one. Omit it and the session has no end user, so its generations match no actor-scoped quota.\n",
9239
+ "required": false,
9240
+ "type": "string",
9241
+ "in": "body"
9242
+ },
9243
+ {
9244
+ "name": "auto_generate",
9245
+ "description": "When true, automatically triggers generation after each user message.",
9246
+ "required": false,
9247
+ "type": "boolean",
9248
+ "in": "body"
9249
+ },
9250
+ {
9251
+ "name": "tool_context",
9252
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this session. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
9253
+ "required": false,
9254
+ "type": "object",
9255
+ "in": "body"
9256
+ },
9257
+ {
9258
+ "name": "inactivity_ttl_seconds",
9259
+ "description": "Number of seconds of inactivity after which the session expires. 0 means the session never expires.",
9260
+ "required": false,
9261
+ "type": "integer",
9262
+ "in": "body"
9263
+ },
9264
+ {
9265
+ "name": "message_delay_seconds",
9266
+ "description": "Number of seconds to wait after the last user message before sending to the LLM. Acts as a debounce: each new message resets the timer. null or absent means no delay (immediate processing).\n",
9267
+ "required": false,
9268
+ "type": "integer",
9269
+ "in": "body"
9270
+ }
9271
+ ]
9272
+ },
9273
+ "get-session": {
9274
+ serviceClass: "Sessions",
9275
+ operationId: "getSession",
9276
+ description: "Returns details of a single session.",
9277
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9278
+ httpMethod: "get",
9279
+ pathParams: ["project_id", "session_id"],
9280
+ queryParams: [],
9281
+ flags: [{
9282
+ "name": "project_id",
9283
+ "description": "Project public ID (proj_ prefix).",
9284
+ "required": true,
9285
+ "type": "string",
9286
+ "in": "path"
9287
+ }, {
9288
+ "name": "session_id",
9289
+ "description": "Session public ID",
9290
+ "required": true,
9291
+ "type": "string",
9292
+ "in": "path"
9293
+ }]
9294
+ },
9295
+ "update-session": {
9296
+ serviceClass: "Sessions",
9297
+ operationId: "updateSession",
9298
+ description: "Updates the session name and/or status.",
9299
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9300
+ httpMethod: "patch",
9301
+ pathParams: ["project_id", "session_id"],
9302
+ queryParams: [],
9303
+ flags: [
9304
+ {
9305
+ "name": "project_id",
9306
+ "description": "Project public ID (proj_ prefix).",
9307
+ "required": true,
9308
+ "type": "string",
9309
+ "in": "path"
9310
+ },
9311
+ {
9312
+ "name": "session_id",
9313
+ "description": "Session public ID",
9314
+ "required": true,
9315
+ "type": "string",
9316
+ "in": "path"
9317
+ },
9318
+ {
9319
+ "name": "name",
9320
+ "description": "Session name (set to null to clear)",
9321
+ "required": false,
9322
+ "type": "string",
9323
+ "in": "body"
9324
+ },
9325
+ {
9326
+ "name": "status",
9327
+ "description": "Session status",
9328
+ "required": false,
9329
+ "type": "string",
9330
+ "in": "body"
9331
+ },
9332
+ {
9333
+ "name": "auto_generate",
9334
+ "description": "Enable or disable automatic generation after user messages.",
9335
+ "required": false,
9336
+ "type": "boolean",
9337
+ "in": "body"
9338
+ },
9339
+ {
9340
+ "name": "tool_context",
9341
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this session. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
9342
+ "required": false,
9343
+ "type": "object",
9344
+ "in": "body"
9345
+ },
9346
+ {
9347
+ "name": "inactivity_ttl_seconds",
9348
+ "description": "Number of seconds of inactivity after which the session expires. 0 means the session never expires. Updates the stored TTL; the inactivity clock continues from the last activity timestamp.\n",
9349
+ "required": false,
9350
+ "type": "integer",
9351
+ "in": "body"
9352
+ },
9353
+ {
9354
+ "name": "message_delay_seconds",
9355
+ "description": "Number of seconds to wait after the last user message before sending to the LLM. Acts as a debounce: each new message resets the timer. Set to null to disable the delay.\n",
9356
+ "required": false,
9357
+ "type": "integer",
9358
+ "in": "body"
9359
+ }
9360
+ ]
9361
+ },
9362
+ "delete-session": {
9363
+ serviceClass: "Sessions",
9364
+ operationId: "deleteSession",
9365
+ description: "Deletes the session and its underlying conversation and messages. The session's actor is not deleted. Generations and traces produced by the session are not deleted either, since they are not linked to the session or conversation.",
9366
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9367
+ httpMethod: "delete",
9368
+ pathParams: ["project_id", "session_id"],
9369
+ queryParams: [],
9370
+ flags: [{
9371
+ "name": "project_id",
9372
+ "description": "Project public ID (proj_ prefix).",
9373
+ "required": true,
9374
+ "type": "string",
9375
+ "in": "path"
9376
+ }, {
9377
+ "name": "session_id",
9378
+ "description": "Session public ID",
9379
+ "required": true,
9380
+ "type": "string",
9381
+ "in": "path"
9382
+ }]
9383
+ },
9384
+ "add-session-message": {
9385
+ serviceClass: "Sessions",
9386
+ operationId: "addSessionMessage",
9387
+ description: "Saves a user message to the session. When autoGenerate is enabled on the session and no generation is currently in progress, generation is triggered automatically and the response mirrors GenerateSessionResponse. Otherwise returns the saved user message.",
9388
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9389
+ httpMethod: "post",
9390
+ pathParams: ["project_id", "session_id"],
9391
+ queryParams: [],
9392
+ flags: [
9393
+ {
9394
+ "name": "project_id",
9395
+ "description": "Project public ID (proj_ prefix).",
9396
+ "required": true,
9397
+ "type": "string",
9398
+ "in": "path"
9399
+ },
9400
+ {
9401
+ "name": "session_id",
9402
+ "description": "Session public ID",
9403
+ "required": true,
9404
+ "type": "string",
9405
+ "in": "path"
9406
+ },
9407
+ {
9408
+ "name": "message",
9409
+ "description": "User message text",
9410
+ "required": false,
9411
+ "type": "string",
9412
+ "in": "body"
9413
+ },
9414
+ {
9415
+ "name": "tool_context",
9416
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this generation. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
9417
+ "required": false,
9418
+ "type": "object",
9419
+ "in": "body"
9420
+ },
9421
+ {
9422
+ "name": "idempotency_key",
9423
+ "description": "Optional deduplication key scoped to this session. If a message with the same key already exists in the session, the original message is returned with HTTP 200 and no new message or generation is triggered.\n",
9424
+ "required": false,
9425
+ "type": "string",
9426
+ "in": "body"
9427
+ },
9428
+ {
9429
+ "name": "document_id",
9430
+ "description": "Public ID of a document used as the user message content.",
9431
+ "required": false,
9432
+ "type": "string",
9433
+ "in": "body"
9434
+ }
9435
+ ]
9436
+ },
9437
+ "generate-session-response": {
9438
+ serviceClass: "Sessions",
9439
+ operationId: "generateSessionResponse",
9440
+ description: "Triggers the agent to generate a response based on the current conversation. Background by default: returns `202 Accepted` immediately while the generation runs. Pass ?wait=true to block and receive the assistant reply (or a requires_action status if the agent needs client tool outputs) in the response.",
9441
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9442
+ httpMethod: "post",
9443
+ pathParams: ["project_id", "session_id"],
9444
+ queryParams: ["wait"],
9445
+ flags: [
9446
+ {
9447
+ "name": "project_id",
9448
+ "description": "Project public ID (proj_ prefix).",
9449
+ "required": true,
9450
+ "type": "string",
9451
+ "in": "path"
9452
+ },
9453
+ {
9454
+ "name": "session_id",
9455
+ "description": "Session public ID",
9456
+ "required": true,
9457
+ "type": "string",
9458
+ "in": "path"
9459
+ },
9460
+ {
9461
+ "name": "wait",
9462
+ "description": "When omitted or `false` (default), generation runs in the background and `202 Accepted` is returned immediately. Pass `true` to block until the generation settles and receive the result.",
9463
+ "required": false,
9464
+ "type": "boolean",
9465
+ "in": "query"
9466
+ },
9467
+ {
9468
+ "name": "model",
9469
+ "description": "Optional model override",
9470
+ "required": false,
9471
+ "type": "string",
9472
+ "in": "body"
9473
+ },
9474
+ {
9475
+ "name": "tool_context",
9476
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this generation. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
9477
+ "required": false,
9478
+ "type": "object",
9479
+ "in": "body"
9480
+ }
9481
+ ]
9482
+ },
9483
+ "submit-session-tool-outputs": {
9484
+ serviceClass: "Sessions",
9485
+ operationId: "submitSessionToolOutputs",
9486
+ description: "Submits client tool outputs for a generation that returned requires_action. The agent continues its loop and returns the final or next requires_action result.",
9487
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9488
+ httpMethod: "post",
9489
+ pathParams: ["project_id", "session_id"],
9490
+ queryParams: [],
9491
+ flags: [
9492
+ {
9493
+ "name": "project_id",
9494
+ "description": "Project public ID (proj_ prefix).",
9495
+ "required": true,
9496
+ "type": "string",
9497
+ "in": "path"
9498
+ },
9499
+ {
9500
+ "name": "session_id",
9501
+ "description": "Session public ID",
9502
+ "required": true,
9503
+ "type": "string",
9504
+ "in": "path"
9505
+ },
9506
+ {
9507
+ "name": "generation_id",
9508
+ "description": "The generation ID from the requires_action response",
9509
+ "required": true,
9510
+ "type": "string",
9511
+ "in": "body"
9512
+ },
9513
+ {
9514
+ "name": "tool_outputs",
9515
+ "description": "",
9516
+ "required": true,
9517
+ "type": "array",
9518
+ "in": "body"
9519
+ }
9520
+ ]
9521
+ },
9522
+ "fork-session": {
9523
+ serviceClass: "Sessions",
9524
+ operationId: "forkSession",
9525
+ description: "Branches a new session from a point in this session's history: same context, different continuation. The fork gets its own conversation whose messages **reference the same documents** as the parent rather than copying them, so there is one stored copy of the content and a retention purge erases it from both. Recorded tool results ride along on those messages and are **replayed** as model input on the fork's next turn — forking never re-invokes a tool, so exploring a \"what if\" cannot send an email or charge a card a second time. The consequence to accept is that a forked turn sees the tool data as it was, not as it is now. The fork is created **inert**: `auto_generate` is false and no generation is triggered. Drive it with the normal message and generate endpoints. The fork has no actor — attach one only if the branch is meant to be driven by the same end user, since `single_session_per_actor` agents allow one open session per actor.",
9526
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9527
+ httpMethod: "post",
9528
+ pathParams: ["project_id", "session_id"],
9529
+ queryParams: [],
9530
+ flags: [
9531
+ {
9532
+ "name": "project_id",
9533
+ "description": "Project public ID (proj_ prefix).",
9534
+ "required": true,
9535
+ "type": "string",
9536
+ "in": "path"
9537
+ },
9538
+ {
9539
+ "name": "session_id",
9540
+ "description": "Session public ID",
9541
+ "required": true,
9542
+ "type": "string",
9543
+ "in": "path"
9544
+ },
9545
+ {
9546
+ "name": "fork_at_position",
9547
+ "description": "The parent conversation `position` to branch after. Messages at positions 0..N are carried into the fork. Omit it to branch at the tip (the whole history).\n",
9548
+ "required": false,
9549
+ "type": "integer",
9550
+ "in": "body"
9551
+ },
9552
+ {
9553
+ "name": "agent_id",
9554
+ "description": "Agent the fork runs against. Defaults to the parent session's agent; overriding it is the point of forking — same context, a different agent or agent version. Must belong to the same project as the session being forked.\n",
9555
+ "required": false,
9556
+ "type": "string",
9557
+ "in": "body"
9558
+ },
9559
+ {
9560
+ "name": "name",
9561
+ "description": "Optional name for the forked session",
9562
+ "required": false,
9563
+ "type": "string",
9564
+ "in": "body"
9565
+ },
9566
+ {
9567
+ "name": "tags",
9568
+ "description": "Optional tags for the forked session",
9569
+ "required": false,
9570
+ "type": "object",
9571
+ "in": "body"
9572
+ },
9573
+ {
9574
+ "name": "tool_context",
9575
+ "description": "Overrides the parent's `tool_context` on the fork. Omit it and the fork inherits the parent's, so the branch is faithful to the run it came from.\n",
9576
+ "required": false,
9577
+ "type": "object",
9578
+ "in": "body"
9579
+ }
9580
+ ]
9581
+ },
9582
+ "list-session-forks": {
9583
+ serviceClass: "Sessions",
9584
+ operationId: "listSessionForks",
9585
+ description: "Returns the sessions forked directly from this one. One level of lineage: a fork of a fork is listed under its own parent.",
9586
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9587
+ httpMethod: "get",
9588
+ pathParams: ["project_id", "session_id"],
9589
+ queryParams: ["limit", "offset"],
9590
+ flags: [
9591
+ {
9592
+ "name": "project_id",
9593
+ "description": "Project public ID (proj_ prefix).",
9594
+ "required": true,
9595
+ "type": "string",
9596
+ "in": "path"
9597
+ },
9598
+ {
9599
+ "name": "session_id",
9600
+ "description": "Session public ID",
9601
+ "required": true,
9602
+ "type": "string",
9603
+ "in": "path"
9604
+ },
9605
+ {
9606
+ "name": "limit",
9607
+ "description": "",
9608
+ "required": false,
9609
+ "type": "integer",
9610
+ "in": "query"
9611
+ },
9612
+ {
9613
+ "name": "offset",
9614
+ "description": "",
9615
+ "required": false,
9616
+ "type": "integer",
9617
+ "in": "query"
9618
+ }
9619
+ ]
9620
+ },
9621
+ "get-session-tags": {
9622
+ serviceClass: "Sessions",
9623
+ operationId: "getSessionTags",
9624
+ description: "Returns the session's tags object.",
9625
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9626
+ httpMethod: "get",
9627
+ pathParams: ["project_id", "session_id"],
9628
+ queryParams: [],
9629
+ flags: [{
9630
+ "name": "project_id",
9631
+ "description": "Project public ID (proj_ prefix).",
9632
+ "required": true,
9633
+ "type": "string",
9634
+ "in": "path"
9635
+ }, {
9636
+ "name": "session_id",
9637
+ "description": "Session public ID",
9638
+ "required": true,
9639
+ "type": "string",
9640
+ "in": "path"
9641
+ }]
9642
+ },
9643
+ "replace-session-tags": {
9644
+ serviceClass: "Sessions",
9645
+ operationId: "replaceSessionTags",
9646
+ description: "Replaces all tags on the session.",
9647
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9648
+ httpMethod: "put",
9649
+ pathParams: ["project_id", "session_id"],
9650
+ queryParams: [],
9651
+ flags: [{
9652
+ "name": "project_id",
9653
+ "description": "Project public ID (proj_ prefix).",
9654
+ "required": true,
9655
+ "type": "string",
9656
+ "in": "path"
9657
+ }, {
9658
+ "name": "session_id",
9659
+ "description": "Session public ID",
9660
+ "required": true,
9661
+ "type": "string",
9662
+ "in": "path"
9663
+ }]
9664
+ },
9665
+ "merge-session-tags": {
9666
+ serviceClass: "Sessions",
9667
+ operationId: "mergeSessionTags",
9668
+ description: "Merges the provided tags into the session's existing tags.",
9669
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
9670
+ httpMethod: "patch",
9671
+ pathParams: ["project_id", "session_id"],
9672
+ queryParams: [],
9673
+ flags: [{
9674
+ "name": "project_id",
9675
+ "description": "Project public ID (proj_ prefix).",
9676
+ "required": true,
9677
+ "type": "string",
9678
+ "in": "path"
9679
+ }, {
9680
+ "name": "session_id",
9681
+ "description": "Session public ID",
9682
+ "required": true,
9683
+ "type": "string",
9684
+ "in": "path"
9685
+ }]
9686
+ },
9687
+ "list-tasks": {
9688
+ serviceClass: "Tasks",
9689
+ operationId: "listTasks",
9690
+ description: "Lists tasks (the board query). Filter by workflow, state, status, or assignee — `GET /tasks?workflow_id=...&state=...` is one board column.",
9691
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9692
+ httpMethod: "get",
9693
+ pathParams: ["project_id"],
9694
+ queryParams: [
9695
+ "workflow_id",
9696
+ "state",
9697
+ "status",
9698
+ "assignee",
9699
+ "limit",
9700
+ "offset"
9701
+ ],
9702
+ flags: [
9703
+ {
9704
+ "name": "project_id",
9705
+ "description": "Project public ID (proj_ prefix).",
9706
+ "required": true,
9707
+ "type": "string",
9708
+ "in": "path"
9709
+ },
9710
+ {
9711
+ "name": "workflow_id",
9712
+ "description": "",
9713
+ "required": false,
9714
+ "type": "string",
9715
+ "in": "query"
9716
+ },
9717
+ {
9718
+ "name": "state",
9719
+ "description": "",
9720
+ "required": false,
9721
+ "type": "string",
9722
+ "in": "query"
9723
+ },
9724
+ {
9725
+ "name": "status",
9726
+ "description": "",
9727
+ "required": false,
9728
+ "type": "string",
9729
+ "in": "query"
9730
+ },
9731
+ {
9732
+ "name": "assignee",
9733
+ "description": "",
9734
+ "required": false,
9735
+ "type": "string",
9736
+ "in": "query"
9737
+ },
9738
+ {
9739
+ "name": "limit",
9740
+ "description": "Maximum number of results to return",
9741
+ "required": false,
9742
+ "type": "integer",
9743
+ "in": "query"
9744
+ },
9745
+ {
9746
+ "name": "offset",
9747
+ "description": "Number of results to skip",
9748
+ "required": false,
9749
+ "type": "integer",
9750
+ "in": "query"
9751
+ }
9752
+ ]
9753
+ },
9754
+ "create-task": {
9755
+ serviceClass: "Tasks",
9756
+ operationId: "createTask",
9757
+ description: "Creates a task bound to a workflow. By default the task is placed in the workflow's initial state; passing `state` places it directly in that named state instead — an alternate entry point for starting a task mid-flow (e.g. \"a new recorte for an existing theme by id\"), rather than re-submitting from the initial state and hoping a guard or similarity gate recognizes it. Entering the resulting state, initial or named, behaves identically: that state's `on_enter` automation fires and its `stalled_after` clock arms.",
9758
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9759
+ httpMethod: "post",
9760
+ pathParams: ["project_id"],
9761
+ queryParams: [],
9762
+ flags: [
9763
+ {
9764
+ "name": "project_id",
9765
+ "description": "Project public ID (proj_ prefix).",
9766
+ "required": true,
9767
+ "type": "string",
9768
+ "in": "path"
9769
+ },
9770
+ {
9771
+ "name": "workflow_id",
9772
+ "description": "",
9773
+ "required": true,
9774
+ "type": "string",
9775
+ "in": "body"
9776
+ },
9777
+ {
9778
+ "name": "title",
9779
+ "description": "",
9780
+ "required": true,
9781
+ "type": "string",
9782
+ "in": "body"
9783
+ },
9784
+ {
9785
+ "name": "payload",
9786
+ "description": "",
9787
+ "required": false,
9788
+ "type": "object",
9789
+ "in": "body"
9790
+ },
9791
+ {
9792
+ "name": "assignee",
9793
+ "description": "",
9794
+ "required": false,
9795
+ "type": "string",
9796
+ "in": "body"
9797
+ },
9798
+ {
9799
+ "name": "state",
9800
+ "description": "Name of a declared workflow state to create the task in directly, instead of the workflow's `initial` state. Must name a state declared on the workflow, or the request is rejected with `TASK_STATE_NOT_FOUND` (400). Defaults to the `initial` state.",
9801
+ "required": false,
9802
+ "type": "string",
9803
+ "in": "body"
9804
+ },
9805
+ {
9806
+ "name": "tool_context",
9807
+ "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call made by this task's automation dispatches — the agent generations a state's `on_enter` starts, and the agent nodes of any orchestration run it starts. The header name is `X-Naturali-Context-` plus the key verbatim; no character is re-cased.\nCreation is the task's first move, so this is the bag the entry state's `on_enter` runs with. Each transition may replace it (see `TransitionTaskRequest.tool_context`).\nThe reserved identity keys (`sessionId`, `actorId`, `actorExternalId`) are stripped in any casing and re-derived server-side, so a task-dispatched generation cannot forge them. A key outside the HTTP header-name grammar is rejected with `INVALID_TOOL_CONTEXT_KEY` (400).\nWrite-only: the stored bag is never returned by any task read, and it is cleared when the task reaches a terminal state.",
9808
+ "required": false,
9809
+ "type": "object",
9810
+ "in": "body"
9811
+ }
9812
+ ]
9813
+ },
9814
+ "get-task": {
9815
+ serviceClass: "Tasks",
9816
+ operationId: "getTask",
9817
+ description: "Retrieves a task, including its active dispatch and automation status.",
9818
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9819
+ httpMethod: "get",
9820
+ pathParams: ["project_id", "task_id"],
9821
+ queryParams: [],
9822
+ flags: [{
9823
+ "name": "project_id",
9824
+ "description": "Project public ID (proj_ prefix).",
9825
+ "required": true,
9826
+ "type": "string",
9827
+ "in": "path"
9828
+ }, {
9829
+ "name": "task_id",
9830
+ "description": "",
9831
+ "required": true,
9832
+ "type": "string",
9833
+ "in": "path"
9834
+ }]
9835
+ },
9836
+ "update-task": {
9837
+ serviceClass: "Tasks",
9838
+ operationId: "updateTask",
9839
+ description: "Updates a task's payload, title, or assignee. `state` is never directly writable — move it with a transition; sending a `state` field is rejected as an unknown field (`VALIDATION_FAILED`). `payload` is shallow-merged over the existing payload (PATCH semantics): keys the request omits are preserved. The payload is caller-owned; the automation result lives in the read-only `last_result` field, which no patch can reach. The merged payload is validated against the workflow's `payload_schema`.",
9840
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9841
+ httpMethod: "patch",
9842
+ pathParams: ["project_id", "task_id"],
9843
+ queryParams: [],
9844
+ flags: [
9845
+ {
9846
+ "name": "project_id",
9847
+ "description": "Project public ID (proj_ prefix).",
9848
+ "required": true,
9849
+ "type": "string",
9850
+ "in": "path"
9851
+ },
9852
+ {
9853
+ "name": "task_id",
9854
+ "description": "",
9855
+ "required": true,
9856
+ "type": "string",
9857
+ "in": "path"
9858
+ },
9859
+ {
9860
+ "name": "title",
9861
+ "description": "",
9862
+ "required": false,
9863
+ "type": "string",
9864
+ "in": "body"
9865
+ },
9866
+ {
9867
+ "name": "payload",
9868
+ "description": "Partial payload, shallow-merged over the existing payload. Omitted keys are preserved; provided keys overwrite. The merged result must satisfy the workflow's payload_schema.",
9869
+ "required": false,
9870
+ "type": "object",
9871
+ "in": "body"
9872
+ },
9873
+ {
9874
+ "name": "assignee",
9875
+ "description": "",
9876
+ "required": false,
9877
+ "type": "string",
9878
+ "in": "body"
9879
+ }
9880
+ ]
9881
+ },
9882
+ "delete-task": {
9883
+ serviceClass: "Tasks",
9884
+ operationId: "deleteTask",
9885
+ description: "Deletes a task. Its transition history cascades.",
9886
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9887
+ httpMethod: "delete",
9888
+ pathParams: ["project_id", "task_id"],
9889
+ queryParams: [],
9890
+ flags: [{
9891
+ "name": "project_id",
9892
+ "description": "Project public ID (proj_ prefix).",
9893
+ "required": true,
9894
+ "type": "string",
9895
+ "in": "path"
9896
+ }, {
9897
+ "name": "task_id",
9898
+ "description": "",
9899
+ "required": true,
9900
+ "type": "string",
9901
+ "in": "path"
9902
+ }]
9903
+ },
9904
+ "transition-task": {
9905
+ serviceClass: "Tasks",
9906
+ operationId: "transitionTask",
9907
+ description: "Fires a named transition on a task. The transition must exist in the workflow and be valid from the task's current state; its guard must pass. This is the single path every state change routes through. A transition declaring `requires_approval` does not move the task — it parks a pending ApprovalItem and returns the task with `pending_transition` set; the move applies only when the approval is approved.",
9908
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9909
+ httpMethod: "post",
9910
+ pathParams: ["project_id", "task_id"],
9911
+ queryParams: [],
9912
+ flags: [
9913
+ {
9914
+ "name": "project_id",
9915
+ "description": "Project public ID (proj_ prefix).",
9916
+ "required": true,
9917
+ "type": "string",
9918
+ "in": "path"
9919
+ },
9920
+ {
9921
+ "name": "task_id",
9922
+ "description": "",
9923
+ "required": true,
9924
+ "type": "string",
9925
+ "in": "path"
9926
+ },
9927
+ {
9928
+ "name": "transition",
9929
+ "description": "",
9930
+ "required": true,
9931
+ "type": "string",
9932
+ "in": "body"
9933
+ },
9934
+ {
9935
+ "name": "note",
9936
+ "description": "",
9937
+ "required": false,
9938
+ "type": "string",
9939
+ "in": "body"
9940
+ },
9941
+ {
9942
+ "name": "tool_context",
9943
+ "description": "Caller context for the automation dispatches the task makes from here on, forwarded as `X-Naturali-Context-<key>` headers on their tool calls.\nSupplying it **replaces** the task's stored bag wholesale; omitting it keeps the current one, so the context follows whoever last moved the task and survives every move that does not speak about it — including an approval gate, a retry, and an automation hop. Send an empty object to clear it without closing the task.\nThe reserved identity keys (`sessionId`, `actorId`, `actorExternalId`) are stripped in any casing and re-derived server-side. A key outside the HTTP header-name grammar is rejected with `INVALID_TOOL_CONTEXT_KEY` (400).\nWrite-only: never returned by a task read, and cleared when the transition closes the task.",
9944
+ "required": false,
9945
+ "type": "object",
9946
+ "in": "body"
9947
+ }
9948
+ ]
9949
+ },
9950
+ "get-task-history": {
9951
+ serviceClass: "Tasks",
9952
+ operationId: "getTaskHistory",
9953
+ description: "Returns the append-only transition history of a task.",
9954
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tasks",
9955
+ httpMethod: "get",
9956
+ pathParams: ["project_id", "task_id"],
9957
+ queryParams: [],
9958
+ flags: [{
9959
+ "name": "project_id",
9960
+ "description": "Project public ID (proj_ prefix).",
9961
+ "required": true,
9962
+ "type": "string",
9963
+ "in": "path"
9964
+ }, {
9965
+ "name": "task_id",
9966
+ "description": "",
9967
+ "required": true,
9968
+ "type": "string",
9969
+ "in": "path"
9970
+ }]
9971
+ },
9972
+ "list-tools": {
9973
+ serviceClass: "Tools",
9974
+ operationId: "listTools",
9975
+ description: "Returns all tools in the project.",
9976
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
9977
+ httpMethod: "get",
9978
+ pathParams: ["project_id"],
9979
+ queryParams: ["limit", "offset"],
9980
+ flags: [
9981
+ {
9982
+ "name": "project_id",
9983
+ "description": "Project public ID (proj_ prefix).",
9984
+ "required": true,
9985
+ "type": "string",
9986
+ "in": "path"
9987
+ },
9988
+ {
9989
+ "name": "limit",
9990
+ "description": "Maximum number of results to return",
9991
+ "required": false,
9992
+ "type": "integer",
9993
+ "in": "query"
9994
+ },
9995
+ {
9996
+ "name": "offset",
9997
+ "description": "Number of results to skip",
9998
+ "required": false,
9999
+ "type": "integer",
10000
+ "in": "query"
10001
+ }
10002
+ ]
10003
+ },
10004
+ "create-tool": {
10005
+ serviceClass: "Tools",
10006
+ operationId: "createTool",
10007
+ description: "Creates a new tool in the project.",
10008
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10009
+ httpMethod: "post",
10010
+ pathParams: ["project_id"],
10011
+ queryParams: [],
10012
+ flags: [
10013
+ {
10014
+ "name": "project_id",
10015
+ "description": "Project public ID (proj_ prefix).",
10016
+ "required": true,
8319
10017
  "type": "string",
8320
10018
  "in": "path"
8321
10019
  },
8322
10020
  {
8323
- "name": "session_id",
8324
- "description": "Session public ID",
10021
+ "name": "name",
10022
+ "description": "Tool name",
8325
10023
  "required": true,
8326
10024
  "type": "string",
8327
- "in": "path"
10025
+ "in": "body"
8328
10026
  },
8329
10027
  {
8330
- "name": "wait",
8331
- "description": "When omitted or `false` (default), generation runs in the background and `202 Accepted` is returned immediately. Pass `true` to block until the generation settles and receive the result.",
10028
+ "name": "type",
10029
+ "description": "Tool type (default http)",
8332
10030
  "required": false,
8333
- "type": "boolean",
8334
- "in": "query"
10031
+ "type": "string",
10032
+ "in": "body"
8335
10033
  },
8336
10034
  {
8337
- "name": "model",
8338
- "description": "Optional model override",
10035
+ "name": "description",
10036
+ "description": "What the tool does",
8339
10037
  "required": false,
8340
10038
  "type": "string",
8341
10039
  "in": "body"
8342
10040
  },
8343
10041
  {
8344
- "name": "tool_context",
8345
- "description": "Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this generation. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.",
10042
+ "name": "parameters",
10043
+ "description": "JSON Schema for tool input",
10044
+ "required": false,
10045
+ "type": "object",
10046
+ "in": "body"
10047
+ },
10048
+ {
10049
+ "name": "execute",
10050
+ "description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
10051
+ "required": false,
10052
+ "type": "object",
10053
+ "in": "body"
10054
+ },
10055
+ {
10056
+ "name": "mcp",
10057
+ "description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
10058
+ "required": false,
10059
+ "type": "object",
10060
+ "in": "body"
10061
+ },
10062
+ {
10063
+ "name": "actions",
10064
+ "description": "Allowlist of actions. For `mcp` tools: an optional allowlist of MCP tool names to scope the server surface — omit or set `null` to expose every tool the MCP server offers. Ignored for other tool types.",
10065
+ "required": false,
10066
+ "type": "array",
10067
+ "in": "body"
10068
+ },
10069
+ {
10070
+ "name": "denied_actions",
10071
+ "description": "For `mcp` tools: an optional denylist of MCP tool names to hide. Applied after `actions` and taking precedence over it. Use it to scope a read+write MCP server read-only by denying just the write tools. Omit or set `null` to deny nothing. Ignored for other tool types.",
10072
+ "required": false,
10073
+ "type": "array",
10074
+ "in": "body"
10075
+ },
10076
+ {
10077
+ "name": "context_keys",
10078
+ "description": "Optional allowlist of `tool_context` keys that may be forwarded to this tool as prefixed context headers (`X-Naturali-Context-<key>` by default). When `null` or omitted, every key in the caller's `tool_context` is forwarded — the behavior of every tool created before this field existed. When set, only the listed keys are, so a per-user credential in `tool_context` can be confined to the tools that need it; `[]` forwards none. The server-pinned identity keys (`sessionId`, `actorId`, `actorExternalId`) are always forwarded. A key consumed by a `{{context:<key>}}` token in this tool's own headers is substituted regardless of this list — the tool declared that header itself.",
10079
+ "required": false,
10080
+ "type": "array",
10081
+ "in": "body"
10082
+ },
10083
+ {
10084
+ "name": "preset_parameters",
10085
+ "description": "Fixed parameters merged into every action-based tool call. Keys matching fields in the action's input schema are removed from the schema shown to the model and injected automatically at execution time.",
10086
+ "required": false,
10087
+ "type": "object",
10088
+ "in": "body"
10089
+ },
10090
+ {
10091
+ "name": "pipeline",
10092
+ "description": "Pipeline definition for `pipeline` tools. See the `pipeline` field on the Tool schema for the full structure.",
10093
+ "required": false,
10094
+ "type": "object",
10095
+ "in": "body"
10096
+ },
10097
+ {
10098
+ "name": "output_mapping",
10099
+ "description": "Universal JSON Logic mapping applied to the tool's raw result. See the `output_mapping` field on the Tool schema for details.",
8346
10100
  "required": false,
8347
10101
  "type": "object",
8348
10102
  "in": "body"
10103
+ },
10104
+ {
10105
+ "name": "guardrail_ids",
10106
+ "description": "Guardrails attached at the tool scope.",
10107
+ "required": false,
10108
+ "type": "array",
10109
+ "in": "body"
8349
10110
  }
8350
10111
  ]
8351
10112
  },
8352
- "submit-session-tool-outputs": {
8353
- serviceClass: "Sessions",
8354
- operationId: "submitSessionToolOutputs",
8355
- description: "Submits client tool outputs for a generation that returned requires_action. The agent continues its loop and returns the final or next requires_action result.",
8356
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8357
- httpMethod: "post",
8358
- pathParams: ["project_id", "session_id"],
10113
+ "get-tool": {
10114
+ serviceClass: "Tools",
10115
+ operationId: "getTool",
10116
+ description: "Returns a single tool by ID.",
10117
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10118
+ httpMethod: "get",
10119
+ pathParams: ["project_id", "tool_id"],
10120
+ queryParams: [],
10121
+ flags: [{
10122
+ "name": "project_id",
10123
+ "description": "Project public ID (proj_ prefix).",
10124
+ "required": true,
10125
+ "type": "string",
10126
+ "in": "path"
10127
+ }, {
10128
+ "name": "tool_id",
10129
+ "description": "",
10130
+ "required": true,
10131
+ "type": "string",
10132
+ "in": "path"
10133
+ }]
10134
+ },
10135
+ "update-tool": {
10136
+ serviceClass: "Tools",
10137
+ operationId: "updateTool",
10138
+ description: "Updates an existing tool.",
10139
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10140
+ httpMethod: "patch",
10141
+ pathParams: ["project_id", "tool_id"],
8359
10142
  queryParams: [],
8360
10143
  flags: [
8361
10144
  {
@@ -8366,35 +10149,134 @@ const routes = {
8366
10149
  "in": "path"
8367
10150
  },
8368
10151
  {
8369
- "name": "session_id",
8370
- "description": "Session public ID",
10152
+ "name": "tool_id",
10153
+ "description": "",
8371
10154
  "required": true,
8372
10155
  "type": "string",
8373
10156
  "in": "path"
8374
10157
  },
8375
10158
  {
8376
- "name": "generation_id",
8377
- "description": "The generation ID from the requires_action response",
8378
- "required": true,
10159
+ "name": "name",
10160
+ "description": "",
10161
+ "required": false,
8379
10162
  "type": "string",
8380
10163
  "in": "body"
8381
10164
  },
8382
10165
  {
8383
- "name": "tool_outputs",
10166
+ "name": "type",
8384
10167
  "description": "",
8385
- "required": true,
10168
+ "required": false,
10169
+ "type": "string",
10170
+ "in": "body"
10171
+ },
10172
+ {
10173
+ "name": "description",
10174
+ "description": "",
10175
+ "required": false,
10176
+ "type": "string",
10177
+ "in": "body"
10178
+ },
10179
+ {
10180
+ "name": "parameters",
10181
+ "description": "",
10182
+ "required": false,
10183
+ "type": "object",
10184
+ "in": "body"
10185
+ },
10186
+ {
10187
+ "name": "execute",
10188
+ "description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
10189
+ "required": false,
10190
+ "type": "object",
10191
+ "in": "body"
10192
+ },
10193
+ {
10194
+ "name": "mcp",
10195
+ "description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
10196
+ "required": false,
10197
+ "type": "object",
10198
+ "in": "body"
10199
+ },
10200
+ {
10201
+ "name": "actions",
10202
+ "description": "Allowlist of actions. For `mcp` tools: an optional allowlist of MCP tool names to scope the server surface (`null` exposes every tool). Ignored for other tool types.",
10203
+ "required": false,
10204
+ "type": "array",
10205
+ "in": "body"
10206
+ },
10207
+ {
10208
+ "name": "denied_actions",
10209
+ "description": "For `mcp` tools: an optional denylist of MCP tool names to hide. Applied after `actions` and taking precedence over it. Use it to scope a read+write MCP server read-only by denying just the write tools. `null` denies nothing. Ignored for other tool types.",
10210
+ "required": false,
10211
+ "type": "array",
10212
+ "in": "body"
10213
+ },
10214
+ {
10215
+ "name": "context_keys",
10216
+ "description": "Optional allowlist of `tool_context` keys that may be forwarded to this tool as prefixed context headers (`X-Naturali-Context-<key>` by default). When `null` or omitted, every key in the caller's `tool_context` is forwarded — the behavior of every tool created before this field existed. When set, only the listed keys are, so a per-user credential in `tool_context` can be confined to the tools that need it; `[]` forwards none. The server-pinned identity keys (`sessionId`, `actorId`, `actorExternalId`) are always forwarded. A key consumed by a `{{context:<key>}}` token in this tool's own headers is substituted regardless of this list — the tool declared that header itself.",
10217
+ "required": false,
10218
+ "type": "array",
10219
+ "in": "body"
10220
+ },
10221
+ {
10222
+ "name": "preset_parameters",
10223
+ "description": "Fixed parameters merged into every action-based tool call. Keys matching fields in the action's input schema are removed from the schema shown to the model and injected automatically at execution time.",
10224
+ "required": false,
10225
+ "type": "object",
10226
+ "in": "body"
10227
+ },
10228
+ {
10229
+ "name": "pipeline",
10230
+ "description": "Pipeline definition for `pipeline` tools. See the `pipeline` field on the Tool schema for the full structure.",
10231
+ "required": false,
10232
+ "type": "object",
10233
+ "in": "body"
10234
+ },
10235
+ {
10236
+ "name": "output_mapping",
10237
+ "description": "Universal JSON Logic mapping applied to the tool's raw result. See the `output_mapping` field on the Tool schema for details.",
10238
+ "required": false,
10239
+ "type": "object",
10240
+ "in": "body"
10241
+ },
10242
+ {
10243
+ "name": "guardrail_ids",
10244
+ "description": "Guardrails attached at the tool scope.",
10245
+ "required": false,
8386
10246
  "type": "array",
8387
10247
  "in": "body"
8388
10248
  }
8389
10249
  ]
8390
10250
  },
8391
- "fork-session": {
8392
- serviceClass: "Sessions",
8393
- operationId: "forkSession",
8394
- description: "Branches a new session from a point in this session's history: same context, different continuation. The fork gets its own conversation whose messages **reference the same documents** as the parent rather than copying them, so there is one stored copy of the content and a retention purge erases it from both. Recorded tool results ride along on those messages and are **replayed** as model input on the fork's next turn — forking never re-invokes a tool, so exploring a \"what if\" cannot send an email or charge a card a second time. The consequence to accept is that a forked turn sees the tool data as it was, not as it is now. The fork is created **inert**: `auto_generate` is false and no generation is triggered. Drive it with the normal message and generate endpoints. The fork has no actor — attach one only if the branch is meant to be driven by the same end user, since `single_session_per_actor` agents allow one open session per actor.",
8395
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
10251
+ "delete-tool": {
10252
+ serviceClass: "Tools",
10253
+ operationId: "deleteTool",
10254
+ description: "Deletes a tool by ID.",
10255
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10256
+ httpMethod: "delete",
10257
+ pathParams: ["project_id", "tool_id"],
10258
+ queryParams: [],
10259
+ flags: [{
10260
+ "name": "project_id",
10261
+ "description": "Project public ID (proj_ prefix).",
10262
+ "required": true,
10263
+ "type": "string",
10264
+ "in": "path"
10265
+ }, {
10266
+ "name": "tool_id",
10267
+ "description": "",
10268
+ "required": true,
10269
+ "type": "string",
10270
+ "in": "path"
10271
+ }]
10272
+ },
10273
+ "call-tool": {
10274
+ serviceClass: "Tools",
10275
+ operationId: "callTool",
10276
+ description: "Directly invokes a tool and returns its output. Supported for `http`, `mcp` and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input. For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` (\"not available on this tool\") before any outbound request is made. `preset_parameters` stored on the tool are merged with the caller-supplied `input` before execution; preset keys take lower precedence.",
10277
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
8396
10278
  httpMethod: "post",
8397
- pathParams: ["project_id", "session_id"],
10279
+ pathParams: ["project_id", "tool_id"],
8398
10280
  queryParams: [],
8399
10281
  flags: [
8400
10282
  {
@@ -8405,56 +10287,35 @@ const routes = {
8405
10287
  "in": "path"
8406
10288
  },
8407
10289
  {
8408
- "name": "session_id",
8409
- "description": "Session public ID",
10290
+ "name": "tool_id",
10291
+ "description": "",
8410
10292
  "required": true,
8411
10293
  "type": "string",
8412
10294
  "in": "path"
8413
10295
  },
8414
10296
  {
8415
- "name": "fork_at_position",
8416
- "description": "The parent conversation `position` to branch after. Messages at positions 0..N are carried into the fork. Omit it to branch at the tip (the whole history).\n",
8417
- "required": false,
8418
- "type": "integer",
8419
- "in": "body"
8420
- },
8421
- {
8422
- "name": "agent_id",
8423
- "description": "Agent the fork runs against. Defaults to the parent session's agent; overriding it is the point of forking — same context, a different agent or agent version. Must belong to the same project as the session being forked.\n",
8424
- "required": false,
8425
- "type": "string",
8426
- "in": "body"
8427
- },
8428
- {
8429
- "name": "name",
8430
- "description": "Optional name for the forked session",
10297
+ "name": "action",
10298
+ "description": "For `mcp` tools: the MCP tool name to invoke (must be in the tool's `actions` allowlist when one is set, and must not be in its `denied_actions` denylist). Ignored for `http` tools.\n",
8431
10299
  "required": false,
8432
10300
  "type": "string",
8433
10301
  "in": "body"
8434
10302
  },
8435
10303
  {
8436
- "name": "tags",
8437
- "description": "Optional tags for the forked session",
8438
- "required": false,
8439
- "type": "object",
8440
- "in": "body"
8441
- },
8442
- {
8443
- "name": "tool_context",
8444
- "description": "Overrides the parent's `tool_context` on the fork. Omit it and the fork inherits the parent's, so the branch is faithful to the run it came from.\n",
10304
+ "name": "input",
10305
+ "description": "Input parameters for the tool call. These are merged with the tool's `preset_parameters` before execution (caller-supplied values take precedence).\n",
8445
10306
  "required": false,
8446
10307
  "type": "object",
8447
10308
  "in": "body"
8448
10309
  }
8449
10310
  ]
8450
10311
  },
8451
- "list-session-forks": {
8452
- serviceClass: "Sessions",
8453
- operationId: "listSessionForks",
8454
- description: "Returns the sessions forked directly from this one. One level of lineage: a fork of a fork is listed under its own parent.",
8455
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
10312
+ "list-traces": {
10313
+ serviceClass: "Traces",
10314
+ operationId: "listTraces",
10315
+ description: "Returns a paginated list of execution traces for the project.",
10316
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
8456
10317
  httpMethod: "get",
8457
- pathParams: ["project_id", "session_id"],
10318
+ pathParams: ["project_id"],
8458
10319
  queryParams: ["limit", "offset"],
8459
10320
  flags: [
8460
10321
  {
@@ -8464,36 +10325,29 @@ const routes = {
8464
10325
  "type": "string",
8465
10326
  "in": "path"
8466
10327
  },
8467
- {
8468
- "name": "session_id",
8469
- "description": "Session public ID",
8470
- "required": true,
8471
- "type": "string",
8472
- "in": "path"
8473
- },
8474
10328
  {
8475
10329
  "name": "limit",
8476
- "description": "",
10330
+ "description": "Maximum number of results to return",
8477
10331
  "required": false,
8478
10332
  "type": "integer",
8479
10333
  "in": "query"
8480
10334
  },
8481
10335
  {
8482
10336
  "name": "offset",
8483
- "description": "",
10337
+ "description": "Number of results to skip",
8484
10338
  "required": false,
8485
10339
  "type": "integer",
8486
10340
  "in": "query"
8487
10341
  }
8488
10342
  ]
8489
10343
  },
8490
- "get-session-tags": {
8491
- serviceClass: "Sessions",
8492
- operationId: "getSessionTags",
8493
- description: "Returns the session's tags object.",
8494
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
10344
+ "get-trace": {
10345
+ serviceClass: "Traces",
10346
+ operationId: "getTrace",
10347
+ description: "Returns a single trace by ID.",
10348
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
8495
10349
  httpMethod: "get",
8496
- pathParams: ["project_id", "session_id"],
10350
+ pathParams: ["project_id", "trace_id"],
8497
10351
  queryParams: [],
8498
10352
  flags: [{
8499
10353
  "name": "project_id",
@@ -8502,42 +10356,52 @@ const routes = {
8502
10356
  "type": "string",
8503
10357
  "in": "path"
8504
10358
  }, {
8505
- "name": "session_id",
8506
- "description": "Session public ID",
10359
+ "name": "trace_id",
10360
+ "description": "Public ID of the trace",
8507
10361
  "required": true,
8508
10362
  "type": "string",
8509
10363
  "in": "path"
8510
10364
  }]
8511
10365
  },
8512
- "replace-session-tags": {
8513
- serviceClass: "Sessions",
8514
- operationId: "replaceSessionTags",
8515
- description: "Replaces all tags on the session.",
8516
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8517
- httpMethod: "put",
8518
- pathParams: ["project_id", "session_id"],
8519
- queryParams: [],
8520
- flags: [{
8521
- "name": "project_id",
8522
- "description": "Project public ID (proj_ prefix).",
8523
- "required": true,
8524
- "type": "string",
8525
- "in": "path"
8526
- }, {
8527
- "name": "session_id",
8528
- "description": "Session public ID",
8529
- "required": true,
8530
- "type": "string",
8531
- "in": "path"
8532
- }]
10366
+ "get-trace-tree": {
10367
+ serviceClass: "Traces",
10368
+ operationId: "getTraceTree",
10369
+ description: "Returns the full execution tree rooted at the given trace (or its root if the given trace is a child). Each node represents one agent's execution session. The `children` array contains traces triggered by sub-agent tool calls from that trace.",
10370
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
10371
+ httpMethod: "get",
10372
+ pathParams: ["project_id", "trace_id"],
10373
+ queryParams: ["include"],
10374
+ flags: [
10375
+ {
10376
+ "name": "project_id",
10377
+ "description": "Project public ID (proj_ prefix).",
10378
+ "required": true,
10379
+ "type": "string",
10380
+ "in": "path"
10381
+ },
10382
+ {
10383
+ "name": "trace_id",
10384
+ "description": "Public ID of any trace in the tree (root or child)",
10385
+ "required": true,
10386
+ "type": "string",
10387
+ "in": "path"
10388
+ },
10389
+ {
10390
+ "name": "include",
10391
+ "description": "Comma-separated list of related resources to embed on each node. Supported value: `generations` — attaches all generations that belong to each trace node (including sub-agent generations linked via `initiator_generation_id`).\n",
10392
+ "required": false,
10393
+ "type": "string",
10394
+ "in": "query"
10395
+ }
10396
+ ]
8533
10397
  },
8534
- "merge-session-tags": {
8535
- serviceClass: "Sessions",
8536
- operationId: "mergeSessionTags",
8537
- description: "Merges the provided tags into the session's existing tags.",
8538
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/sessions",
8539
- httpMethod: "patch",
8540
- pathParams: ["project_id", "session_id"],
10398
+ "purge-trace-content": {
10399
+ serviceClass: "Traces",
10400
+ operationId: "purgeTraceContent",
10401
+ description: "Deletes the trace's steps object from storage and clears its content columns (`file_id`, `error`), cascading to every descendant trace and to all of their generations. A descendant holds its own steps object covering the same run, so the cascade is what makes the erasure complete rather than merely partial. The rows survive as auditable skeletons with `content_redacted_at` set — ids, timestamps, step counts, and the generations' usage-attribution fields are preserved, because the billing and audit ledger must outlive a tenant's erasure of the content. A purged trace therefore reads back as a skeleton, not a 404: a 404 would prove nothing. Idempotent — purging an already-purged trace succeeds and leaves the original `content_redacted_at` in place.",
10402
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
10403
+ httpMethod: "delete",
10404
+ pathParams: ["project_id", "trace_id"],
8541
10405
  queryParams: [],
8542
10406
  flags: [{
8543
10407
  "name": "project_id",
@@ -8546,21 +10410,26 @@ const routes = {
8546
10410
  "type": "string",
8547
10411
  "in": "path"
8548
10412
  }, {
8549
- "name": "session_id",
8550
- "description": "Session public ID",
10413
+ "name": "trace_id",
10414
+ "description": "Public ID of the trace",
8551
10415
  "required": true,
8552
10416
  "type": "string",
8553
10417
  "in": "path"
8554
10418
  }]
8555
10419
  },
8556
- "list-tools": {
8557
- serviceClass: "Tools",
8558
- operationId: "listTools",
8559
- description: "Returns all tools in the project.",
8560
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10420
+ "list-triggers": {
10421
+ serviceClass: "Triggers",
10422
+ operationId: "listTriggers",
10423
+ description: "Lists triggers. Filter by project, starter type, or target type.",
10424
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
8561
10425
  httpMethod: "get",
8562
10426
  pathParams: ["project_id"],
8563
- queryParams: ["limit", "offset"],
10427
+ queryParams: [
10428
+ "type",
10429
+ "target_type",
10430
+ "limit",
10431
+ "offset"
10432
+ ],
8564
10433
  flags: [
8565
10434
  {
8566
10435
  "name": "project_id",
@@ -8569,6 +10438,20 @@ const routes = {
8569
10438
  "type": "string",
8570
10439
  "in": "path"
8571
10440
  },
10441
+ {
10442
+ "name": "type",
10443
+ "description": "",
10444
+ "required": false,
10445
+ "type": "string",
10446
+ "in": "query"
10447
+ },
10448
+ {
10449
+ "name": "target_type",
10450
+ "description": "",
10451
+ "required": false,
10452
+ "type": "string",
10453
+ "in": "query"
10454
+ },
8572
10455
  {
8573
10456
  "name": "limit",
8574
10457
  "description": "Maximum number of results to return",
@@ -8585,11 +10468,11 @@ const routes = {
8585
10468
  }
8586
10469
  ]
8587
10470
  },
8588
- "create-tool": {
8589
- serviceClass: "Tools",
8590
- operationId: "createTool",
8591
- description: "Creates a new tool in the project.",
8592
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
10471
+ "create-trigger": {
10472
+ serviceClass: "Triggers",
10473
+ operationId: "createTrigger",
10474
+ description: "Creates a new trigger for a project",
10475
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
8593
10476
  httpMethod: "post",
8594
10477
  pathParams: ["project_id"],
8595
10478
  queryParams: [],
@@ -8603,104 +10486,193 @@ const routes = {
8603
10486
  },
8604
10487
  {
8605
10488
  "name": "name",
8606
- "description": "Tool name",
10489
+ "description": "",
8607
10490
  "required": true,
8608
10491
  "type": "string",
8609
10492
  "in": "body"
8610
10493
  },
10494
+ {
10495
+ "name": "description",
10496
+ "description": "",
10497
+ "required": false,
10498
+ "type": "string",
10499
+ "in": "body"
10500
+ },
8611
10501
  {
8612
10502
  "name": "type",
8613
- "description": "Tool type (default http)",
10503
+ "description": "",
10504
+ "required": true,
10505
+ "type": "string",
10506
+ "in": "body"
10507
+ },
10508
+ {
10509
+ "name": "target_type",
10510
+ "description": "",
10511
+ "required": true,
10512
+ "type": "string",
10513
+ "in": "body"
10514
+ },
10515
+ {
10516
+ "name": "target_id",
10517
+ "description": "",
10518
+ "required": true,
10519
+ "type": "string",
10520
+ "in": "body"
10521
+ },
10522
+ {
10523
+ "name": "action",
10524
+ "description": "Tool targets only — the action for mcp tools",
8614
10525
  "required": false,
8615
10526
  "type": "string",
8616
10527
  "in": "body"
8617
10528
  },
8618
10529
  {
8619
- "name": "description",
8620
- "description": "What the tool does",
10530
+ "name": "input",
10531
+ "description": "",
10532
+ "required": false,
10533
+ "type": "object",
10534
+ "in": "body"
10535
+ },
10536
+ {
10537
+ "name": "cron",
10538
+ "description": "5-field cron expression (UTC). Required when type is schedule",
10539
+ "required": false,
10540
+ "type": "string",
10541
+ "in": "body"
10542
+ },
10543
+ {
10544
+ "name": "active",
10545
+ "description": "",
10546
+ "required": false,
10547
+ "type": "boolean",
10548
+ "in": "body"
10549
+ },
10550
+ {
10551
+ "name": "policy_id",
10552
+ "description": "",
8621
10553
  "required": false,
8622
10554
  "type": "string",
8623
- "in": "body"
10555
+ "in": "body"
10556
+ }
10557
+ ]
10558
+ },
10559
+ "get-trigger": {
10560
+ serviceClass: "Triggers",
10561
+ operationId: "getTrigger",
10562
+ description: "Retrieves the details of a specific trigger",
10563
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10564
+ httpMethod: "get",
10565
+ pathParams: ["project_id", "trigger_id"],
10566
+ queryParams: [],
10567
+ flags: [{
10568
+ "name": "project_id",
10569
+ "description": "Project public ID (proj_ prefix).",
10570
+ "required": true,
10571
+ "type": "string",
10572
+ "in": "path"
10573
+ }, {
10574
+ "name": "trigger_id",
10575
+ "description": "",
10576
+ "required": true,
10577
+ "type": "string",
10578
+ "in": "path"
10579
+ }]
10580
+ },
10581
+ "update-trigger": {
10582
+ serviceClass: "Triggers",
10583
+ operationId: "updateTrigger",
10584
+ description: "Updates an existing trigger's configuration. The type is immutable.",
10585
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10586
+ httpMethod: "patch",
10587
+ pathParams: ["project_id", "trigger_id"],
10588
+ queryParams: [],
10589
+ flags: [
10590
+ {
10591
+ "name": "project_id",
10592
+ "description": "Project public ID (proj_ prefix).",
10593
+ "required": true,
10594
+ "type": "string",
10595
+ "in": "path"
8624
10596
  },
8625
10597
  {
8626
- "name": "parameters",
8627
- "description": "JSON Schema for tool input",
8628
- "required": false,
8629
- "type": "object",
8630
- "in": "body"
10598
+ "name": "trigger_id",
10599
+ "description": "",
10600
+ "required": true,
10601
+ "type": "string",
10602
+ "in": "path"
8631
10603
  },
8632
10604
  {
8633
- "name": "execute",
8634
- "description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
10605
+ "name": "name",
10606
+ "description": "",
8635
10607
  "required": false,
8636
- "type": "object",
10608
+ "type": "string",
8637
10609
  "in": "body"
8638
10610
  },
8639
10611
  {
8640
- "name": "mcp",
8641
- "description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
10612
+ "name": "description",
10613
+ "description": "",
8642
10614
  "required": false,
8643
- "type": "object",
10615
+ "type": "string",
8644
10616
  "in": "body"
8645
10617
  },
8646
10618
  {
8647
- "name": "actions",
8648
- "description": "Allowlist of actions. For `mcp` tools: an optional allowlist of MCP tool names to scope the server surface — omit or set `null` to expose every tool the MCP server offers. Ignored for other tool types.",
10619
+ "name": "target_type",
10620
+ "description": "",
8649
10621
  "required": false,
8650
- "type": "array",
10622
+ "type": "string",
8651
10623
  "in": "body"
8652
10624
  },
8653
10625
  {
8654
- "name": "denied_actions",
8655
- "description": "For `mcp` tools: an optional denylist of MCP tool names to hide. Applied after `actions` and taking precedence over it. Use it to scope a read+write MCP server read-only by denying just the write tools. Omit or set `null` to deny nothing. Ignored for other tool types.",
10626
+ "name": "target_id",
10627
+ "description": "",
8656
10628
  "required": false,
8657
- "type": "array",
10629
+ "type": "string",
8658
10630
  "in": "body"
8659
10631
  },
8660
10632
  {
8661
- "name": "context_keys",
8662
- "description": "Optional allowlist of `tool_context` keys that may be forwarded to this tool as prefixed context headers (`X-Naturali-Context-<key>` by default). When `null` or omitted, every key in the caller's `tool_context` is forwarded — the behavior of every tool created before this field existed. When set, only the listed keys are, so a per-user credential in `tool_context` can be confined to the tools that need it; `[]` forwards none. The server-pinned identity keys (`sessionId`, `actorId`, `actorExternalId`) are always forwarded. A key consumed by a `{{context:<key>}}` token in this tool's own headers is substituted regardless of this list — the tool declared that header itself.",
10633
+ "name": "action",
10634
+ "description": "",
8663
10635
  "required": false,
8664
- "type": "array",
10636
+ "type": "string",
8665
10637
  "in": "body"
8666
10638
  },
8667
10639
  {
8668
- "name": "preset_parameters",
8669
- "description": "Fixed parameters merged into every action-based tool call. Keys matching fields in the action's input schema are removed from the schema shown to the model and injected automatically at execution time.",
10640
+ "name": "input",
10641
+ "description": "",
8670
10642
  "required": false,
8671
10643
  "type": "object",
8672
10644
  "in": "body"
8673
10645
  },
8674
10646
  {
8675
- "name": "pipeline",
8676
- "description": "Pipeline definition for `pipeline` tools. See the `pipeline` field on the Tool schema for the full structure.",
10647
+ "name": "cron",
10648
+ "description": "",
8677
10649
  "required": false,
8678
- "type": "object",
10650
+ "type": "string",
8679
10651
  "in": "body"
8680
10652
  },
8681
10653
  {
8682
- "name": "output_mapping",
8683
- "description": "Universal JSON Logic mapping applied to the tool's raw result. See the `output_mapping` field on the Tool schema for details.",
10654
+ "name": "active",
10655
+ "description": "",
8684
10656
  "required": false,
8685
- "type": "object",
10657
+ "type": "boolean",
8686
10658
  "in": "body"
8687
10659
  },
8688
10660
  {
8689
- "name": "guardrail_ids",
8690
- "description": "Guardrails attached at the tool scope.",
10661
+ "name": "policy_id",
10662
+ "description": "",
8691
10663
  "required": false,
8692
- "type": "array",
10664
+ "type": "string",
8693
10665
  "in": "body"
8694
10666
  }
8695
10667
  ]
8696
10668
  },
8697
- "get-tool": {
8698
- serviceClass: "Tools",
8699
- operationId: "getTool",
8700
- description: "Returns a single tool by ID.",
8701
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
8702
- httpMethod: "get",
8703
- pathParams: ["project_id", "tool_id"],
10669
+ "delete-trigger": {
10670
+ serviceClass: "Triggers",
10671
+ operationId: "deleteTrigger",
10672
+ description: "Deletes a trigger",
10673
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10674
+ httpMethod: "delete",
10675
+ pathParams: ["project_id", "trigger_id"],
8704
10676
  queryParams: [],
8705
10677
  flags: [{
8706
10678
  "name": "project_id",
@@ -8709,20 +10681,20 @@ const routes = {
8709
10681
  "type": "string",
8710
10682
  "in": "path"
8711
10683
  }, {
8712
- "name": "tool_id",
10684
+ "name": "trigger_id",
8713
10685
  "description": "",
8714
10686
  "required": true,
8715
10687
  "type": "string",
8716
10688
  "in": "path"
8717
10689
  }]
8718
10690
  },
8719
- "update-tool": {
8720
- serviceClass: "Tools",
8721
- operationId: "updateTool",
8722
- description: "Updates an existing tool.",
8723
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
8724
- httpMethod: "patch",
8725
- pathParams: ["project_id", "tool_id"],
10691
+ "fire-trigger": {
10692
+ serviceClass: "Triggers",
10693
+ operationId: "fireTrigger",
10694
+ description: "Fires a trigger synchronously and returns the terminal firing record. The firing itself always settles here; an `eval` target's run is queued rather than executed inline, so the record names a `queued` run to poll.",
10695
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10696
+ httpMethod: "post",
10697
+ pathParams: ["project_id", "trigger_id"],
8726
10698
  queryParams: [],
8727
10699
  flags: [
8728
10700
  {
@@ -8733,112 +10705,241 @@ const routes = {
8733
10705
  "in": "path"
8734
10706
  },
8735
10707
  {
8736
- "name": "tool_id",
10708
+ "name": "trigger_id",
8737
10709
  "description": "",
8738
10710
  "required": true,
8739
10711
  "type": "string",
8740
10712
  "in": "path"
8741
10713
  },
8742
10714
  {
8743
- "name": "name",
8744
- "description": "",
10715
+ "name": "input",
10716
+ "description": "Fire-time input, shallow-merged over the trigger's static input. For `eval` targets it may carry `agent_version` and `baseline_run_id`.",
8745
10717
  "required": false,
8746
- "type": "string",
10718
+ "type": "object",
8747
10719
  "in": "body"
8748
- },
10720
+ }
10721
+ ]
10722
+ },
10723
+ "get-trigger-secret": {
10724
+ serviceClass: "Triggers",
10725
+ operationId: "getTriggerSecret",
10726
+ description: "Retrieves the signing secret for a webhook trigger",
10727
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10728
+ httpMethod: "get",
10729
+ pathParams: ["project_id", "trigger_id"],
10730
+ queryParams: [],
10731
+ flags: [{
10732
+ "name": "project_id",
10733
+ "description": "Project public ID (proj_ prefix).",
10734
+ "required": true,
10735
+ "type": "string",
10736
+ "in": "path"
10737
+ }, {
10738
+ "name": "trigger_id",
10739
+ "description": "",
10740
+ "required": true,
10741
+ "type": "string",
10742
+ "in": "path"
10743
+ }]
10744
+ },
10745
+ "rotate-trigger-secret": {
10746
+ serviceClass: "Triggers",
10747
+ operationId: "rotateTriggerSecret",
10748
+ description: "Rotates the signing secret for a webhook trigger",
10749
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10750
+ httpMethod: "post",
10751
+ pathParams: ["project_id", "trigger_id"],
10752
+ queryParams: [],
10753
+ flags: [{
10754
+ "name": "project_id",
10755
+ "description": "Project public ID (proj_ prefix).",
10756
+ "required": true,
10757
+ "type": "string",
10758
+ "in": "path"
10759
+ }, {
10760
+ "name": "trigger_id",
10761
+ "description": "",
10762
+ "required": true,
10763
+ "type": "string",
10764
+ "in": "path"
10765
+ }]
10766
+ },
10767
+ "list-trigger-firings": {
10768
+ serviceClass: "Triggers",
10769
+ operationId: "listTriggerFirings",
10770
+ description: "Lists firings for a trigger (trigger_id is required).",
10771
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10772
+ httpMethod: "get",
10773
+ pathParams: ["project_id"],
10774
+ queryParams: [
10775
+ "trigger_id",
10776
+ "limit",
10777
+ "offset"
10778
+ ],
10779
+ flags: [
8749
10780
  {
8750
- "name": "type",
8751
- "description": "",
8752
- "required": false,
10781
+ "name": "project_id",
10782
+ "description": "Project public ID (proj_ prefix).",
10783
+ "required": true,
8753
10784
  "type": "string",
8754
- "in": "body"
10785
+ "in": "path"
8755
10786
  },
8756
10787
  {
8757
- "name": "description",
8758
- "description": "",
8759
- "required": false,
10788
+ "name": "trigger_id",
10789
+ "description": "Trigger to list firings for (trg_...)",
10790
+ "required": true,
8760
10791
  "type": "string",
8761
- "in": "body"
10792
+ "in": "query"
8762
10793
  },
8763
10794
  {
8764
- "name": "parameters",
10795
+ "name": "limit",
8765
10796
  "description": "",
8766
10797
  "required": false,
8767
- "type": "object",
8768
- "in": "body"
10798
+ "type": "integer",
10799
+ "in": "query"
8769
10800
  },
8770
10801
  {
8771
- "name": "execute",
8772
- "description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
10802
+ "name": "offset",
10803
+ "description": "",
8773
10804
  "required": false,
8774
- "type": "object",
8775
- "in": "body"
8776
- },
10805
+ "type": "integer",
10806
+ "in": "query"
10807
+ }
10808
+ ]
10809
+ },
10810
+ "get-trigger-firing": {
10811
+ serviceClass: "Triggers",
10812
+ operationId: "getTriggerFiring",
10813
+ description: "Retrieves the details of a specific trigger firing",
10814
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
10815
+ httpMethod: "get",
10816
+ pathParams: ["project_id", "firing_id"],
10817
+ queryParams: [],
10818
+ flags: [{
10819
+ "name": "project_id",
10820
+ "description": "Project public ID (proj_ prefix).",
10821
+ "required": true,
10822
+ "type": "string",
10823
+ "in": "path"
10824
+ }, {
10825
+ "name": "firing_id",
10826
+ "description": "",
10827
+ "required": true,
10828
+ "type": "string",
10829
+ "in": "path"
10830
+ }]
10831
+ },
10832
+ "get-current-user": {
10833
+ serviceClass: "Users",
10834
+ operationId: "getCurrentUser",
10835
+ description: "Returns the account the presented credential resolves to.",
10836
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/users",
10837
+ httpMethod: "get",
10838
+ pathParams: [],
10839
+ queryParams: [],
10840
+ flags: []
10841
+ },
10842
+ "update-current-user": {
10843
+ serviceClass: "Users",
10844
+ operationId: "updateCurrentUser",
10845
+ description: "Edits the account's display name. `name` is required in the body — send null to clear it — so a request that misspelled the field is rejected rather than answered with a silent 200.",
10846
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/users",
10847
+ httpMethod: "patch",
10848
+ pathParams: [],
10849
+ queryParams: [],
10850
+ flags: [{
10851
+ "name": "name",
10852
+ "description": "Display name; null clears it.",
10853
+ "required": true,
10854
+ "type": "string",
10855
+ "in": "body"
10856
+ }]
10857
+ },
10858
+ "list-webhooks": {
10859
+ serviceClass: "Webhooks",
10860
+ operationId: "listWebhooks",
10861
+ description: "The endpoints registered in the project, newest first.",
10862
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
10863
+ httpMethod: "get",
10864
+ pathParams: ["project_id"],
10865
+ queryParams: ["limit", "cursor"],
10866
+ flags: [
8777
10867
  {
8778
- "name": "mcp",
8779
- "description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
8780
- "required": false,
8781
- "type": "object",
8782
- "in": "body"
10868
+ "name": "project_id",
10869
+ "description": "Project public ID (proj_ prefix).",
10870
+ "required": true,
10871
+ "type": "string",
10872
+ "in": "path"
8783
10873
  },
8784
10874
  {
8785
- "name": "actions",
8786
- "description": "Allowlist of actions. For `mcp` tools: an optional allowlist of MCP tool names to scope the server surface (`null` exposes every tool). Ignored for other tool types.",
10875
+ "name": "limit",
10876
+ "description": "Maximum items per page an integer from 1 to 100 (default 20).",
8787
10877
  "required": false,
8788
- "type": "array",
8789
- "in": "body"
10878
+ "type": "integer",
10879
+ "in": "query"
8790
10880
  },
8791
10881
  {
8792
- "name": "denied_actions",
8793
- "description": "For `mcp` tools: an optional denylist of MCP tool names to hide. Applied after `actions` and taking precedence over it. Use it to scope a read+write MCP server read-only by denying just the write tools. `null` denies nothing. Ignored for other tool types.",
10882
+ "name": "cursor",
10883
+ "description": "Opaque pagination cursor from a previous response's next_cursor.",
8794
10884
  "required": false,
8795
- "type": "array",
8796
- "in": "body"
8797
- },
10885
+ "type": "string",
10886
+ "in": "query"
10887
+ }
10888
+ ]
10889
+ },
10890
+ "create-webhook": {
10891
+ serviceClass: "Webhooks",
10892
+ operationId: "createWebhook",
10893
+ description: "Register an endpoint and subscribe it to one or more event types. The response carries `secret` — the signing key, in plaintext. **This is the only time it is returned.** Store it where your receiver can read it; if you lose it, rotate rather than re-create, so the endpoint keeps its delivery history. Returns `501` on a deployment with no credential-sealing key configured, since the secret could not then be stored safely.",
10894
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
10895
+ httpMethod: "post",
10896
+ pathParams: ["project_id"],
10897
+ queryParams: [],
10898
+ flags: [
8798
10899
  {
8799
- "name": "context_keys",
8800
- "description": "Optional allowlist of `tool_context` keys that may be forwarded to this tool as prefixed context headers (`X-Naturali-Context-<key>` by default). When `null` or omitted, every key in the caller's `tool_context` is forwarded — the behavior of every tool created before this field existed. When set, only the listed keys are, so a per-user credential in `tool_context` can be confined to the tools that need it; `[]` forwards none. The server-pinned identity keys (`sessionId`, `actorId`, `actorExternalId`) are always forwarded. A key consumed by a `{{context:<key>}}` token in this tool's own headers is substituted regardless of this list — the tool declared that header itself.",
8801
- "required": false,
8802
- "type": "array",
8803
- "in": "body"
10900
+ "name": "project_id",
10901
+ "description": "Project public ID (proj_ prefix).",
10902
+ "required": true,
10903
+ "type": "string",
10904
+ "in": "path"
8804
10905
  },
8805
10906
  {
8806
- "name": "preset_parameters",
8807
- "description": "Fixed parameters merged into every action-based tool call. Keys matching fields in the action's input schema are removed from the schema shown to the model and injected automatically at execution time.",
8808
- "required": false,
8809
- "type": "object",
10907
+ "name": "url",
10908
+ "description": "An `https://` endpoint (`http://` is accepted for localhost, so a tunnel works in development).\n",
10909
+ "required": true,
10910
+ "type": "string",
8810
10911
  "in": "body"
8811
10912
  },
8812
10913
  {
8813
- "name": "pipeline",
8814
- "description": "Pipeline definition for `pipeline` tools. See the `pipeline` field on the Tool schema for the full structure.",
8815
- "required": false,
8816
- "type": "object",
10914
+ "name": "events",
10915
+ "description": "Which events this endpoint receives. Each entry is an exact type (`generation.completed`), a resource wildcard (`generation.*`), or `*` for everything. A bare resource name (`generation`) matches nothing and is rejected.\n",
10916
+ "required": true,
10917
+ "type": "array",
8817
10918
  "in": "body"
8818
10919
  },
8819
10920
  {
8820
- "name": "output_mapping",
8821
- "description": "Universal JSON Logic mapping applied to the tool's raw result. See the `output_mapping` field on the Tool schema for details.",
10921
+ "name": "description",
10922
+ "description": "",
8822
10923
  "required": false,
8823
- "type": "object",
10924
+ "type": "string",
8824
10925
  "in": "body"
8825
10926
  },
8826
10927
  {
8827
- "name": "guardrail_ids",
8828
- "description": "Guardrails attached at the tool scope.",
10928
+ "name": "active",
10929
+ "description": "",
8829
10930
  "required": false,
8830
- "type": "array",
10931
+ "type": "boolean",
8831
10932
  "in": "body"
8832
10933
  }
8833
10934
  ]
8834
10935
  },
8835
- "delete-tool": {
8836
- serviceClass: "Tools",
8837
- operationId: "deleteTool",
8838
- description: "Deletes a tool by ID.",
8839
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
8840
- httpMethod: "delete",
8841
- pathParams: ["project_id", "tool_id"],
10936
+ "get-webhook": {
10937
+ serviceClass: "Webhooks",
10938
+ operationId: "getWebhook",
10939
+ description: "Get a webhook",
10940
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
10941
+ httpMethod: "get",
10942
+ pathParams: ["project_id", "webhook_id"],
8842
10943
  queryParams: [],
8843
10944
  flags: [{
8844
10945
  "name": "project_id",
@@ -8847,20 +10948,20 @@ const routes = {
8847
10948
  "type": "string",
8848
10949
  "in": "path"
8849
10950
  }, {
8850
- "name": "tool_id",
8851
- "description": "",
10951
+ "name": "webhook_id",
10952
+ "description": "Webhook public ID (whk_ prefix).",
8852
10953
  "required": true,
8853
10954
  "type": "string",
8854
10955
  "in": "path"
8855
10956
  }]
8856
10957
  },
8857
- "call-tool": {
8858
- serviceClass: "Tools",
8859
- operationId: "callTool",
8860
- description: "Directly invokes a tool and returns its output. Supported for `http`, `mcp` and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input. For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` (\"not available on this tool\") before any outbound request is made. `preset_parameters` stored on the tool are merged with the caller-supplied `input` before execution; preset keys take lower precedence.",
8861
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
8862
- httpMethod: "post",
8863
- pathParams: ["project_id", "tool_id"],
10958
+ "update-webhook": {
10959
+ serviceClass: "Webhooks",
10960
+ operationId: "updateWebhook",
10961
+ description: "Change the destination, the subscription, the label, or whether deliveries are attempted at all. At least one field is required. Setting `active: false` is the reversible half of `DELETE`: deliveries stop, the endpoint and its history stay. It is what to reach for while a receiver is being repaired.",
10962
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
10963
+ httpMethod: "patch",
10964
+ pathParams: ["project_id", "webhook_id"],
8864
10965
  queryParams: [],
8865
10966
  flags: [
8866
10967
  {
@@ -8871,67 +10972,49 @@ const routes = {
8871
10972
  "in": "path"
8872
10973
  },
8873
10974
  {
8874
- "name": "tool_id",
8875
- "description": "",
10975
+ "name": "webhook_id",
10976
+ "description": "Webhook public ID (whk_ prefix).",
8876
10977
  "required": true,
8877
10978
  "type": "string",
8878
10979
  "in": "path"
8879
10980
  },
8880
10981
  {
8881
- "name": "action",
8882
- "description": "For `mcp` tools: the MCP tool name to invoke (must be in the tool's `actions` allowlist when one is set, and must not be in its `denied_actions` denylist). Ignored for `http` tools.\n",
10982
+ "name": "url",
10983
+ "description": "",
8883
10984
  "required": false,
8884
10985
  "type": "string",
8885
10986
  "in": "body"
8886
10987
  },
8887
10988
  {
8888
- "name": "input",
8889
- "description": "Input parameters for the tool call. These are merged with the tool's `preset_parameters` before execution (caller-supplied values take precedence).\n",
10989
+ "name": "events",
10990
+ "description": "Which events this endpoint receives. Each entry is an exact type (`generation.completed`), a resource wildcard (`generation.*`), or `*` for everything. A bare resource name (`generation`) matches nothing and is rejected.\n",
8890
10991
  "required": false,
8891
- "type": "object",
10992
+ "type": "array",
8892
10993
  "in": "body"
8893
- }
8894
- ]
8895
- },
8896
- "list-traces": {
8897
- serviceClass: "Traces",
8898
- operationId: "listTraces",
8899
- description: "Returns a paginated list of execution traces for the project.",
8900
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
8901
- httpMethod: "get",
8902
- pathParams: ["project_id"],
8903
- queryParams: ["limit", "offset"],
8904
- flags: [
8905
- {
8906
- "name": "project_id",
8907
- "description": "Project public ID (proj_ prefix).",
8908
- "required": true,
8909
- "type": "string",
8910
- "in": "path"
8911
10994
  },
8912
10995
  {
8913
- "name": "limit",
8914
- "description": "Maximum number of results to return",
10996
+ "name": "description",
10997
+ "description": "",
8915
10998
  "required": false,
8916
- "type": "integer",
8917
- "in": "query"
10999
+ "type": "string",
11000
+ "in": "body"
8918
11001
  },
8919
11002
  {
8920
- "name": "offset",
8921
- "description": "Number of results to skip",
11003
+ "name": "active",
11004
+ "description": "",
8922
11005
  "required": false,
8923
- "type": "integer",
8924
- "in": "query"
11006
+ "type": "boolean",
11007
+ "in": "body"
8925
11008
  }
8926
11009
  ]
8927
11010
  },
8928
- "get-trace": {
8929
- serviceClass: "Traces",
8930
- operationId: "getTrace",
8931
- description: "Returns a single trace by ID.",
8932
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
8933
- httpMethod: "get",
8934
- pathParams: ["project_id", "trace_id"],
11011
+ "delete-webhook": {
11012
+ serviceClass: "Webhooks",
11013
+ operationId: "deleteWebhook",
11014
+ description: "Removes the endpoint and its delivery records. To stop deliveries while keeping the audit trail, `PATCH` it to `active: false` instead.",
11015
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11016
+ httpMethod: "delete",
11017
+ pathParams: ["project_id", "webhook_id"],
8935
11018
  queryParams: [],
8936
11019
  flags: [{
8937
11020
  "name": "project_id",
@@ -8940,21 +11023,49 @@ const routes = {
8940
11023
  "type": "string",
8941
11024
  "in": "path"
8942
11025
  }, {
8943
- "name": "trace_id",
8944
- "description": "Public ID of the trace",
11026
+ "name": "webhook_id",
11027
+ "description": "Webhook public ID (whk_ prefix).",
8945
11028
  "required": true,
8946
11029
  "type": "string",
8947
11030
  "in": "path"
8948
11031
  }]
8949
11032
  },
8950
- "get-trace-tree": {
8951
- serviceClass: "Traces",
8952
- operationId: "getTraceTree",
8953
- description: "Returns the full execution tree rooted at the given trace (or its root if the given trace is a child). Each node represents one agent's execution session. The `children` array contains traces triggered by sub-agent tool calls from that trace.",
8954
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
11033
+ "rotate-webhook-secret": {
11034
+ serviceClass: "Webhooks",
11035
+ operationId: "rotateWebhookSecret",
11036
+ description: "Issues a new signing secret for the same endpoint and returns it the second and last time a secret is ever returned. This is the `…:rotate-secret` action; the path segment is `{webhook_id}:rotate-secret`. The change takes effect on the next delivery, including retries of deliveries already queued, so roll the new secret out to your receiver promptly. There is no overlap window in which both secrets verify.",
11037
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11038
+ httpMethod: "post",
11039
+ pathParams: ["project_id", "webhook_id"],
11040
+ queryParams: [],
11041
+ flags: [{
11042
+ "name": "project_id",
11043
+ "description": "Project public ID (proj_ prefix).",
11044
+ "required": true,
11045
+ "type": "string",
11046
+ "in": "path"
11047
+ }, {
11048
+ "name": "webhook_id",
11049
+ "description": "Webhook public ID (whk_ prefix).",
11050
+ "required": true,
11051
+ "type": "string",
11052
+ "in": "path"
11053
+ }]
11054
+ },
11055
+ "list-webhook-deliveries": {
11056
+ serviceClass: "Webhooks",
11057
+ operationId: "listWebhookDeliveries",
11058
+ description: "Every delivery attempted in the project, newest first — what was sent, where, how many times, and what came back. Filter by endpoint, by lifecycle status, or by event type. Deliveries are per (event, endpoint): an event matching two subscribed endpoints produces two rows, retried and observed independently.",
11059
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
8955
11060
  httpMethod: "get",
8956
- pathParams: ["project_id", "trace_id"],
8957
- queryParams: ["include"],
11061
+ pathParams: ["project_id"],
11062
+ queryParams: [
11063
+ "limit",
11064
+ "cursor",
11065
+ "webhook_id",
11066
+ "status",
11067
+ "event_type"
11068
+ ],
8958
11069
  flags: [
8959
11070
  {
8960
11071
  "name": "project_id",
@@ -8964,28 +11075,49 @@ const routes = {
8964
11075
  "in": "path"
8965
11076
  },
8966
11077
  {
8967
- "name": "trace_id",
8968
- "description": "Public ID of any trace in the tree (root or child)",
8969
- "required": true,
11078
+ "name": "limit",
11079
+ "description": "Maximum items per page an integer from 1 to 100 (default 20).",
11080
+ "required": false,
11081
+ "type": "integer",
11082
+ "in": "query"
11083
+ },
11084
+ {
11085
+ "name": "cursor",
11086
+ "description": "Opaque pagination cursor from a previous response's next_cursor.",
11087
+ "required": false,
8970
11088
  "type": "string",
8971
- "in": "path"
11089
+ "in": "query"
8972
11090
  },
8973
11091
  {
8974
- "name": "include",
8975
- "description": "Comma-separated list of related resources to embed on each node. Supported value: `generations` — attaches all generations that belong to each trace node (including sub-agent generations linked via `initiator_generation_id`).\n",
11092
+ "name": "webhook_id",
11093
+ "description": "Only deliveries addressed to this endpoint.",
11094
+ "required": false,
11095
+ "type": "string",
11096
+ "in": "query"
11097
+ },
11098
+ {
11099
+ "name": "status",
11100
+ "description": "Only deliveries in this state.",
11101
+ "required": false,
11102
+ "type": "string",
11103
+ "in": "query"
11104
+ },
11105
+ {
11106
+ "name": "event_type",
11107
+ "description": "Only deliveries of this event type.",
8976
11108
  "required": false,
8977
11109
  "type": "string",
8978
11110
  "in": "query"
8979
11111
  }
8980
11112
  ]
8981
11113
  },
8982
- "purge-trace-content": {
8983
- serviceClass: "Traces",
8984
- operationId: "purgeTraceContent",
8985
- description: "Deletes the trace's steps object from storage and clears its content columns (`file_id`, `error`), cascading to every descendant trace and to all of their generations. A descendant holds its own steps object covering the same run, so the cascade is what makes the erasure complete rather than merely partial. The rows survive as auditable skeletons with `content_redacted_at` set — ids, timestamps, step counts, and the generations' usage-attribution fields are preserved, because the billing and audit ledger must outlive a tenant's erasure of the content. A purged trace therefore reads back as a skeleton, not a 404: a 404 would prove nothing. Idempotent — purging an already-purged trace succeeds and leaves the original `content_redacted_at` in place.",
8986
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/traces",
8987
- httpMethod: "delete",
8988
- pathParams: ["project_id", "trace_id"],
11114
+ "get-webhook-delivery": {
11115
+ serviceClass: "Webhooks",
11116
+ operationId: "getWebhookDelivery",
11117
+ description: "One delivery, including the exact payload that was signed and sent.",
11118
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11119
+ httpMethod: "get",
11120
+ pathParams: ["project_id", "delivery_id"],
8989
11121
  queryParams: [],
8990
11122
  flags: [{
8991
11123
  "name": "project_id",
@@ -8994,47 +11126,43 @@ const routes = {
8994
11126
  "type": "string",
8995
11127
  "in": "path"
8996
11128
  }, {
8997
- "name": "trace_id",
8998
- "description": "Public ID of the trace",
11129
+ "name": "delivery_id",
11130
+ "description": "Delivery public ID (whd_ prefix).",
8999
11131
  "required": true,
9000
11132
  "type": "string",
9001
11133
  "in": "path"
9002
11134
  }]
9003
11135
  },
9004
- "get-current-user": {
9005
- serviceClass: "Users",
9006
- operationId: "getCurrentUser",
9007
- description: "Returns the account the presented credential resolves to.",
9008
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/users",
9009
- httpMethod: "get",
9010
- pathParams: [],
9011
- queryParams: [],
9012
- flags: []
9013
- },
9014
- "update-current-user": {
9015
- serviceClass: "Users",
9016
- operationId: "updateCurrentUser",
9017
- description: "Edits the account's display name. `name` is required in the body — send null to clear it — so a request that misspelled the field is rejected rather than answered with a silent 200.",
9018
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/users",
9019
- httpMethod: "patch",
9020
- pathParams: [],
11136
+ "redeliver-webhook-delivery": {
11137
+ serviceClass: "Webhooks",
11138
+ operationId: "redeliverWebhookDelivery",
11139
+ description: "Queue the same event at the same endpoint again — the recovery path for a delivery that failed, or one your receiver dropped. This is the `…:redeliver` action; the path segment is `{delivery_id}:redeliver`. A **new** delivery is created and returned; the original record is left untouched, because its attempt history is the evidence you redelivered on. The event's `id` is carried over unchanged, so a receiver deduping on the event sees the same event twice while one deduping on `X-Naturali-Delivery` sees a distinct delivery.",
11140
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11141
+ httpMethod: "post",
11142
+ pathParams: ["project_id", "delivery_id"],
9021
11143
  queryParams: [],
9022
11144
  flags: [{
9023
- "name": "name",
9024
- "description": "Display name; null clears it.",
11145
+ "name": "project_id",
11146
+ "description": "Project public ID (proj_ prefix).",
9025
11147
  "required": true,
9026
11148
  "type": "string",
9027
- "in": "body"
11149
+ "in": "path"
11150
+ }, {
11151
+ "name": "delivery_id",
11152
+ "description": "Delivery public ID (whd_ prefix).",
11153
+ "required": true,
11154
+ "type": "string",
11155
+ "in": "path"
9028
11156
  }]
9029
11157
  },
9030
- "list-webhooks": {
9031
- serviceClass: "Webhooks",
9032
- operationId: "listWebhooks",
9033
- description: "The endpoints registered in the project, newest first.",
9034
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11158
+ "list-workflows": {
11159
+ serviceClass: "Workflows",
11160
+ operationId: "listWorkflows",
11161
+ description: "Lists workflow definitions in a project.",
11162
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9035
11163
  httpMethod: "get",
9036
11164
  pathParams: ["project_id"],
9037
- queryParams: ["limit", "cursor"],
11165
+ queryParams: ["limit", "offset"],
9038
11166
  flags: [
9039
11167
  {
9040
11168
  "name": "project_id",
@@ -9045,25 +11173,25 @@ const routes = {
9045
11173
  },
9046
11174
  {
9047
11175
  "name": "limit",
9048
- "description": "Maximum items per page — an integer from 1 to 100 (default 20).",
11176
+ "description": "Maximum number of results to return",
9049
11177
  "required": false,
9050
11178
  "type": "integer",
9051
11179
  "in": "query"
9052
11180
  },
9053
11181
  {
9054
- "name": "cursor",
9055
- "description": "Opaque pagination cursor from a previous response's next_cursor.",
11182
+ "name": "offset",
11183
+ "description": "Number of results to skip",
9056
11184
  "required": false,
9057
- "type": "string",
11185
+ "type": "integer",
9058
11186
  "in": "query"
9059
11187
  }
9060
11188
  ]
9061
11189
  },
9062
- "create-webhook": {
9063
- serviceClass: "Webhooks",
9064
- operationId: "createWebhook",
9065
- description: "Register an endpoint and subscribe it to one or more event types. The response carries `secret` — the signing key, in plaintext. **This is the only time it is returned.** Store it where your receiver can read it; if you lose it, rotate rather than re-create, so the endpoint keeps its delivery history. Returns `501` on a deployment with no credential-sealing key configured, since the secret could not then be stored safely.",
9066
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11190
+ "create-workflow": {
11191
+ serviceClass: "Workflows",
11192
+ operationId: "createWorkflow",
11193
+ description: "Creates a new workflow definition. The definition is statically validated.",
11194
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9067
11195
  httpMethod: "post",
9068
11196
  pathParams: ["project_id"],
9069
11197
  queryParams: [],
@@ -9076,42 +11204,56 @@ const routes = {
9076
11204
  "in": "path"
9077
11205
  },
9078
11206
  {
9079
- "name": "url",
9080
- "description": "An `https://` endpoint (`http://` is accepted for localhost, so a tunnel works in development).\n",
11207
+ "name": "name",
11208
+ "description": "",
9081
11209
  "required": true,
9082
11210
  "type": "string",
9083
11211
  "in": "body"
9084
11212
  },
9085
11213
  {
9086
- "name": "events",
9087
- "description": "Which events this endpoint receives. Each entry is an exact type (`generation.completed`), a resource wildcard (`generation.*`), or `*` for everything. A bare resource name (`generation`) matches nothing and is rejected.\n",
11214
+ "name": "description",
11215
+ "description": "",
11216
+ "required": false,
11217
+ "type": "string",
11218
+ "in": "body"
11219
+ },
11220
+ {
11221
+ "name": "states",
11222
+ "description": "",
9088
11223
  "required": true,
9089
11224
  "type": "array",
9090
11225
  "in": "body"
9091
11226
  },
9092
11227
  {
9093
- "name": "description",
11228
+ "name": "transitions",
9094
11229
  "description": "",
9095
- "required": false,
9096
- "type": "string",
11230
+ "required": true,
11231
+ "type": "array",
9097
11232
  "in": "body"
9098
11233
  },
9099
11234
  {
9100
- "name": "active",
11235
+ "name": "payload_schema",
9101
11236
  "description": "",
9102
11237
  "required": false,
9103
- "type": "boolean",
11238
+ "type": "object",
11239
+ "in": "body"
11240
+ },
11241
+ {
11242
+ "name": "version_label",
11243
+ "description": "Optional tag for the version this create archives, e.g. `initial`.",
11244
+ "required": false,
11245
+ "type": "string",
9104
11246
  "in": "body"
9105
11247
  }
9106
11248
  ]
9107
11249
  },
9108
- "get-webhook": {
9109
- serviceClass: "Webhooks",
9110
- operationId: "getWebhook",
9111
- description: "Get a webhook",
9112
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11250
+ "get-workflow": {
11251
+ serviceClass: "Workflows",
11252
+ operationId: "getWorkflow",
11253
+ description: "Retrieves a workflow definition.",
11254
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9113
11255
  httpMethod: "get",
9114
- pathParams: ["project_id", "webhook_id"],
11256
+ pathParams: ["project_id", "workflow_id"],
9115
11257
  queryParams: [],
9116
11258
  flags: [{
9117
11259
  "name": "project_id",
@@ -9120,20 +11262,20 @@ const routes = {
9120
11262
  "type": "string",
9121
11263
  "in": "path"
9122
11264
  }, {
9123
- "name": "webhook_id",
9124
- "description": "Webhook public ID (whk_ prefix).",
11265
+ "name": "workflow_id",
11266
+ "description": "",
9125
11267
  "required": true,
9126
11268
  "type": "string",
9127
11269
  "in": "path"
9128
11270
  }]
9129
11271
  },
9130
- "update-webhook": {
9131
- serviceClass: "Webhooks",
9132
- operationId: "updateWebhook",
9133
- description: "Change the destination, the subscription, the label, or whether deliveries are attempted at all. At least one field is required. Setting `active: false` is the reversible half of `DELETE`: deliveries stop, the endpoint and its history stay. It is what to reach for while a receiver is being repaired.",
9134
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11272
+ "update-workflow": {
11273
+ serviceClass: "Workflows",
11274
+ operationId: "updateWorkflow",
11275
+ description: "Updates a workflow definition. Structural changes (states/transitions) are re-validated. Existing tasks in a removed state stay put but can only leave via transitions valid in the new definition.",
11276
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9135
11277
  httpMethod: "patch",
9136
- pathParams: ["project_id", "webhook_id"],
11278
+ pathParams: ["project_id", "workflow_id"],
9137
11279
  queryParams: [],
9138
11280
  flags: [
9139
11281
  {
@@ -9144,49 +11286,63 @@ const routes = {
9144
11286
  "in": "path"
9145
11287
  },
9146
11288
  {
9147
- "name": "webhook_id",
9148
- "description": "Webhook public ID (whk_ prefix).",
11289
+ "name": "workflow_id",
11290
+ "description": "",
9149
11291
  "required": true,
9150
11292
  "type": "string",
9151
11293
  "in": "path"
9152
11294
  },
9153
11295
  {
9154
- "name": "url",
11296
+ "name": "name",
9155
11297
  "description": "",
9156
11298
  "required": false,
9157
11299
  "type": "string",
9158
11300
  "in": "body"
9159
11301
  },
9160
11302
  {
9161
- "name": "events",
9162
- "description": "Which events this endpoint receives. Each entry is an exact type (`generation.completed`), a resource wildcard (`generation.*`), or `*` for everything. A bare resource name (`generation`) matches nothing and is rejected.\n",
11303
+ "name": "description",
11304
+ "description": "",
11305
+ "required": false,
11306
+ "type": "string",
11307
+ "in": "body"
11308
+ },
11309
+ {
11310
+ "name": "states",
11311
+ "description": "",
9163
11312
  "required": false,
9164
11313
  "type": "array",
9165
11314
  "in": "body"
9166
11315
  },
9167
11316
  {
9168
- "name": "description",
11317
+ "name": "transitions",
9169
11318
  "description": "",
9170
11319
  "required": false,
9171
- "type": "string",
11320
+ "type": "array",
9172
11321
  "in": "body"
9173
11322
  },
9174
11323
  {
9175
- "name": "active",
11324
+ "name": "payload_schema",
9176
11325
  "description": "",
9177
11326
  "required": false,
9178
- "type": "boolean",
11327
+ "type": "object",
11328
+ "in": "body"
11329
+ },
11330
+ {
11331
+ "name": "version_label",
11332
+ "description": "Optional tag for the version this write archives, e.g. `pre-rewire`. Ignored when the write changes no definition field, since no version is archived.",
11333
+ "required": false,
11334
+ "type": "string",
9179
11335
  "in": "body"
9180
11336
  }
9181
11337
  ]
9182
11338
  },
9183
- "delete-webhook": {
9184
- serviceClass: "Webhooks",
9185
- operationId: "deleteWebhook",
9186
- description: "Removes the endpoint and its delivery records. To stop deliveries while keeping the audit trail, `PATCH` it to `active: false` instead.",
9187
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11339
+ "delete-workflow": {
11340
+ serviceClass: "Workflows",
11341
+ operationId: "deleteWorkflow",
11342
+ description: "Deletes a workflow. Rejected while open tasks exist.",
11343
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9188
11344
  httpMethod: "delete",
9189
- pathParams: ["project_id", "webhook_id"],
11345
+ pathParams: ["project_id", "workflow_id"],
9190
11346
  queryParams: [],
9191
11347
  flags: [{
9192
11348
  "name": "project_id",
@@ -9195,49 +11351,21 @@ const routes = {
9195
11351
  "type": "string",
9196
11352
  "in": "path"
9197
11353
  }, {
9198
- "name": "webhook_id",
9199
- "description": "Webhook public ID (whk_ prefix).",
9200
- "required": true,
9201
- "type": "string",
9202
- "in": "path"
9203
- }]
9204
- },
9205
- "rotate-webhook-secret": {
9206
- serviceClass: "Webhooks",
9207
- operationId: "rotateWebhookSecret",
9208
- description: "Issues a new signing secret for the same endpoint and returns it — the second and last time a secret is ever returned. This is the `…:rotate-secret` action; the path segment is `{webhook_id}:rotate-secret`. The change takes effect on the next delivery, including retries of deliveries already queued, so roll the new secret out to your receiver promptly. There is no overlap window in which both secrets verify.",
9209
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
9210
- httpMethod: "post",
9211
- pathParams: ["project_id", "webhook_id"],
9212
- queryParams: [],
9213
- flags: [{
9214
- "name": "project_id",
9215
- "description": "Project public ID (proj_ prefix).",
9216
- "required": true,
9217
- "type": "string",
9218
- "in": "path"
9219
- }, {
9220
- "name": "webhook_id",
9221
- "description": "Webhook public ID (whk_ prefix).",
11354
+ "name": "workflow_id",
11355
+ "description": "",
9222
11356
  "required": true,
9223
11357
  "type": "string",
9224
11358
  "in": "path"
9225
11359
  }]
9226
11360
  },
9227
- "list-webhook-deliveries": {
9228
- serviceClass: "Webhooks",
9229
- operationId: "listWebhookDeliveries",
9230
- description: "Every delivery attempted in the project, newest first what was sent, where, how many times, and what came back. Filter by endpoint, by lifecycle status, or by event type. Deliveries are per (event, endpoint): an event matching two subscribed endpoints produces two rows, retried and observed independently.",
9231
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11361
+ "list-workflow-versions": {
11362
+ serviceClass: "Workflows",
11363
+ operationId: "listWorkflowVersions",
11364
+ description: "Returns the workflow's archived state machines, newest first. A version is written on create and on every subsequent write that changes the definition (`states`, `transitions`, `payload_schema`) through the REST API or a formation apply alike. Metadata-only edits (name, description) do not archive a version. See [Versioning](/docs/modules/workflows#versioning).",
11365
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9232
11366
  httpMethod: "get",
9233
- pathParams: ["project_id"],
9234
- queryParams: [
9235
- "limit",
9236
- "cursor",
9237
- "webhook_id",
9238
- "status",
9239
- "event_type"
9240
- ],
11367
+ pathParams: ["project_id", "workflow_id"],
11368
+ queryParams: ["limit", "offset"],
9241
11369
  flags: [
9242
11370
  {
9243
11371
  "name": "project_id",
@@ -9246,86 +11374,107 @@ const routes = {
9246
11374
  "type": "string",
9247
11375
  "in": "path"
9248
11376
  },
11377
+ {
11378
+ "name": "workflow_id",
11379
+ "description": "",
11380
+ "required": true,
11381
+ "type": "string",
11382
+ "in": "path"
11383
+ },
9249
11384
  {
9250
11385
  "name": "limit",
9251
- "description": "Maximum items per page — an integer from 1 to 100 (default 20).",
11386
+ "description": "Maximum number of results to return",
9252
11387
  "required": false,
9253
11388
  "type": "integer",
9254
11389
  "in": "query"
9255
11390
  },
9256
11391
  {
9257
- "name": "cursor",
9258
- "description": "Opaque pagination cursor from a previous response's next_cursor.",
11392
+ "name": "offset",
11393
+ "description": "Number of results to skip",
9259
11394
  "required": false,
9260
- "type": "string",
11395
+ "type": "integer",
9261
11396
  "in": "query"
9262
- },
11397
+ }
11398
+ ]
11399
+ },
11400
+ "get-workflow-version": {
11401
+ serviceClass: "Workflows",
11402
+ operationId: "getWorkflowVersion",
11403
+ description: "Returns the exact state machine a given version describes. Every task records the version it entered on in `workflow_version` and runs on that machine for its whole life, so this is how you read the definition a task is actually being validated against — including a task whose workflow has been rewired since.",
11404
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
11405
+ httpMethod: "get",
11406
+ pathParams: [
11407
+ "project_id",
11408
+ "workflow_id",
11409
+ "version"
11410
+ ],
11411
+ queryParams: [],
11412
+ flags: [
9263
11413
  {
9264
- "name": "webhook_id",
9265
- "description": "Only deliveries addressed to this endpoint.",
9266
- "required": false,
11414
+ "name": "project_id",
11415
+ "description": "Project public ID (proj_ prefix).",
11416
+ "required": true,
9267
11417
  "type": "string",
9268
- "in": "query"
11418
+ "in": "path"
9269
11419
  },
9270
11420
  {
9271
- "name": "status",
9272
- "description": "Only deliveries in this state.",
9273
- "required": false,
11421
+ "name": "workflow_id",
11422
+ "description": "",
11423
+ "required": true,
9274
11424
  "type": "string",
9275
- "in": "query"
11425
+ "in": "path"
9276
11426
  },
9277
11427
  {
9278
- "name": "event_type",
9279
- "description": "Only deliveries of this event type.",
9280
- "required": false,
9281
- "type": "string",
9282
- "in": "query"
11428
+ "name": "version",
11429
+ "description": "The archived version number",
11430
+ "required": true,
11431
+ "type": "integer",
11432
+ "in": "path"
9283
11433
  }
9284
11434
  ]
9285
11435
  },
9286
- "get-webhook-delivery": {
9287
- serviceClass: "Webhooks",
9288
- operationId: "getWebhookDelivery",
9289
- description: "One delivery, including the exact payload that was signed and sent.",
9290
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
9291
- httpMethod: "get",
9292
- pathParams: ["project_id", "delivery_id"],
9293
- queryParams: [],
9294
- flags: [{
9295
- "name": "project_id",
9296
- "description": "Project public ID (proj_ prefix).",
9297
- "required": true,
9298
- "type": "string",
9299
- "in": "path"
9300
- }, {
9301
- "name": "delivery_id",
9302
- "description": "Delivery public ID (whd_ prefix).",
9303
- "required": true,
9304
- "type": "string",
9305
- "in": "path"
9306
- }]
9307
- },
9308
- "redeliver-webhook-delivery": {
9309
- serviceClass: "Webhooks",
9310
- operationId: "redeliverWebhookDelivery",
9311
- description: "Queue the same event at the same endpoint again — the recovery path for a delivery that failed, or one your receiver dropped. This is the `…:redeliver` action; the path segment is `{delivery_id}:redeliver`. A **new** delivery is created and returned; the original record is left untouched, because its attempt history is the evidence you redelivered on. The event's `id` is carried over unchanged, so a receiver deduping on the event sees the same event twice while one deduping on `X-Naturali-Delivery` sees a distinct delivery.",
9312
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/webhooks",
11436
+ "restore-workflow-version": {
11437
+ serviceClass: "Workflows",
11438
+ operationId: "restoreWorkflowVersion",
11439
+ description: "Writes an archived version's state machine back as the workflow's live definition, which archives it again as a **new** version rather than rewinding the counter so a task pinned to any version in between still runs on the machine it entered on. The restore runs through the ordinary update path, so the archived definition goes through the same validation as an authored one. That includes resolving every `on_enter` dispatch target, so restoring a version whose agent or orchestration has since been deleted fails with `400` rather than writing a definition that would strand a task on entry. Restoring the definition the workflow already holds is a no-op and archives nothing. Tasks already in flight are unaffected either way — a restore is an ordinary edit, and pinning is what keeps it from reaching them.",
11440
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/workflows",
9313
11441
  httpMethod: "post",
9314
- pathParams: ["project_id", "delivery_id"],
11442
+ pathParams: [
11443
+ "project_id",
11444
+ "workflow_id",
11445
+ "version"
11446
+ ],
9315
11447
  queryParams: [],
9316
- flags: [{
9317
- "name": "project_id",
9318
- "description": "Project public ID (proj_ prefix).",
9319
- "required": true,
9320
- "type": "string",
9321
- "in": "path"
9322
- }, {
9323
- "name": "delivery_id",
9324
- "description": "Delivery public ID (whd_ prefix).",
9325
- "required": true,
9326
- "type": "string",
9327
- "in": "path"
9328
- }]
11448
+ flags: [
11449
+ {
11450
+ "name": "project_id",
11451
+ "description": "Project public ID (proj_ prefix).",
11452
+ "required": true,
11453
+ "type": "string",
11454
+ "in": "path"
11455
+ },
11456
+ {
11457
+ "name": "workflow_id",
11458
+ "description": "",
11459
+ "required": true,
11460
+ "type": "string",
11461
+ "in": "path"
11462
+ },
11463
+ {
11464
+ "name": "version",
11465
+ "description": "The archived version number",
11466
+ "required": true,
11467
+ "type": "integer",
11468
+ "in": "path"
11469
+ },
11470
+ {
11471
+ "name": "label",
11472
+ "description": "Optional tag for the new version the restore archives. Defaults to `restored from vN`.",
11473
+ "required": false,
11474
+ "type": "string",
11475
+ "in": "body"
11476
+ }
11477
+ ]
9329
11478
  }
9330
11479
  };
9331
11480
  //#endregion