@nylorun/runtime 0.39.0-beta → 0.41.0-beta

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 (45) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/adapters/streams/s2.js +9 -2
  3. package/dist/api/a2a/endpoint.js +1 -1
  4. package/dist/api/a2a/protocol.d.ts +6 -0
  5. package/dist/api/a2a/protocol.js +13 -0
  6. package/dist/api/a2a/routes.js +1 -0
  7. package/dist/api/components.d.ts +131 -0
  8. package/dist/api/components.js +3 -1
  9. package/dist/api/http/app.js +2 -0
  10. package/dist/api/http/routes/runs.d.ts +8 -0
  11. package/dist/api/http/routes/runs.js +30 -0
  12. package/dist/api/http/routes/triggers.d.ts +2 -1
  13. package/dist/api/http/routes/triggers.js +32 -4
  14. package/dist/api/openapi.js +3 -1
  15. package/dist/gates/policy.d.ts +6 -4
  16. package/dist/gates/policy.js +10 -2
  17. package/dist/harness-api/record.js +51 -6
  18. package/dist/harness-api/start.js +15 -9
  19. package/dist/harness-api/tool-journal.js +3 -0
  20. package/dist/management-openapi.json +11 -6
  21. package/dist/openapi.json +507 -13
  22. package/dist/store/postgres/drizzle/0043_agent_triggers_origin.sql +11 -0
  23. package/dist/store/postgres/drizzle/0044_agent_triggers_origin_backfill.sql +8 -0
  24. package/dist/store/postgres/drizzle/meta/_journal.json +14 -0
  25. package/dist/store/postgres/schema.d.ts +151 -4
  26. package/dist/store/postgres/schema.js +25 -4
  27. package/dist/store/postgres/store.js +20 -2
  28. package/dist/store/types.d.ts +10 -0
  29. package/dist/streams/types.d.ts +16 -1
  30. package/dist/streams/types.js +8 -1
  31. package/dist/tenant/advance.js +7 -0
  32. package/dist/tenant/agent-triggers.d.ts +60 -0
  33. package/dist/tenant/agent-triggers.js +179 -0
  34. package/dist/tenant/agents.d.ts +1 -1
  35. package/dist/tenant/agents.js +5 -1
  36. package/dist/tenant/limits.d.ts +26 -7
  37. package/dist/tenant/limits.js +39 -6
  38. package/dist/tenant/runs-stream.d.ts +51 -0
  39. package/dist/tenant/runs-stream.js +164 -0
  40. package/dist/tenant/sweep.js +3 -0
  41. package/dist/tenant/triggers.d.ts +31 -5
  42. package/dist/tenant/triggers.js +168 -48
  43. package/dist/version.d.ts +1 -1
  44. package/dist/version.js +1 -1
  45. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.41.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - 714bee2: The triggers capability (Host feature `agent-triggers`): an agent-folder/2 folder declares `engine: { triggers: true }` (the root agent's only; `engine.instructions.triggers` replaces its wording), which compiles to `harness.engine.triggers` and offers the root agent the `triggers` tool (`list`, `create`, `delete`) and the text block `triggers@1`. The Runtime serves each call as a `runtime` effect (operation `triggers`, `turn.start.agent.triggers`, Harness API v5.3): a trigger an agent makes is the Agent's (`origin: "agent"`, with its title and the session that made it), runs in the calling session (`session: "this"`) or one of its own (`"own"`, `<session>_t_<id>`), is checked against the limits in force (`runtime.limits.triggers` within the Tenant's), survives upgrades and waits paused while a version lacks the capability; a turn a trigger started can't create one. Tool rules take `kind: "runtime"`, so an `ask` rule can hold a `triggers` call (its interaction carries `metadata.input`); `DELETE /v1/agents/{id}/triggers/{triggerId}` deletes an agent's trigger (`409 trigger_from_manifest` for a manifest's); `GET /v1/runs/stream` serves the Tenant's runs as server-sent events from a cursor (`410 cursor_expired` across a reset). `client.agents.deleteTrigger`, `client.runs.stream` and `nylorun agents triggers rm` follow. The JSON Schemas are republished as `agent-manifest/v8.3`, `harness-manifest/v1.3`, `runtime-manifest/v1.2`, `agent-folder/v1/agent-md.3`, `agent-folder/v1/runtime.2` and `harness-api/v5.3`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Pin core to the tested release.
12
+ - Pin harness to the tested release.
13
+ - Updated dependencies [714bee2]
14
+ - Updated dependencies
15
+ - @nylorun/core@0.35.0-beta
16
+ - @nylorun/harness@0.32.0-beta
17
+
18
+ ## 0.40.0-beta
19
+
20
+ ### Minor Changes
21
+
22
+ - 78787e2: A2A `SendMessage` takes `message.metadata.removeTools` (Host feature `remove-tools`): the tools a new message's turn may not use, by name, as a session message's `removeTools`. `createA2aClient`'s `send` takes `removeTools`.
23
+
3
24
  ## 0.39.0-beta
4
25
 
5
26
  ### Minor Changes
@@ -9,8 +9,9 @@
9
9
  * `<basinPrefix>tn-<ulid>` for a Tenant id `tn_<ulid>`, `…-<g base36>` for generation g.
10
10
  * - The basin is created with `createStreamOnAppend` and `createStreamOnRead`, so
11
11
  * `sessions/<id>` come into existence on first use. Its default stream config
12
- * sets infinite retention, which session streams keep. There are no other
13
- * streams: signals between processes go over Postgres (D48).
12
+ * sets infinite retention, which session streams keep. The Tenant's `runs`
13
+ * stream (D83) is ensured with 7 days' retention (`ensureStream`). There are
14
+ * no other streams: signals between processes go over Postgres (D48).
14
15
  * - Bodies are JSON text in string records. Record timestamps are S2 arrival
15
16
  * times.
16
17
  * - Appends use `appendRetryPolicy: "noSideEffects"`: the SDK retries only
@@ -203,6 +204,12 @@ class S2Streams {
203
204
  throw error;
204
205
  }
205
206
  }
207
+ async ensureStream(tenantId, stream, options) {
208
+ this.checkOpen();
209
+ await this.s2
210
+ .basin(this.basinName(tenantId))
211
+ .streams.ensure({ stream, config: { retentionPolicy: { ageSecs: options.retentionSecs } } }, { signal: this.closing.signal });
212
+ }
206
213
  async listStreams(tenantId, prefix) {
207
214
  this.checkOpen();
208
215
  const names = [];
@@ -72,7 +72,7 @@ export function a2aRoutes(api) {
72
72
  path: "/v1/a2a/agents/{agentId}",
73
73
  tags: TAGS,
74
74
  summary: "Call an agent over A2A",
75
- description: "A2A 1.0 JSON-RPC, for a subject, under the Nylorun profile v2 (Host feature `a2a-profile-v2`). `SendMessage` blocks up to the Runtime limit `a2aWaitMs` (5 minutes by default; then the task is answered still `WORKING`) unless `returnImmediately`; `GetTask` (with `historyLength`), `CancelTask` and `ListTasks`; and the four push notification config methods, plus `configuration.taskPushNotificationConfig` in `SendMessage`: each update is POSTed as one `StreamResponse`, signed with Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webhook-signature` with the Runtime's `a2a.push.secret`) and `X-A2A-Notification-Token`, at least once, retried for up to 24 hours, to hosts the Runtime allows (`a2a.push.allowHosts` for private ones). A message to a busy context is queued and answered with the task that will take it (`TASK_STATE_SUBMITTED`); `message.metadata.delivery: \"reject\"` asks for `UnsupportedOperationError` (reason `CONTEXT_BUSY`) instead. A message is text, one data part, or text with `raw` files (stored as artifacts of the context's session) and `url` files (fetched by the Runtime), each at most the Runtime limit `inlineFileBytes` (20 MiB by default). An approval, question or connection the task waits for (`AUTH_REQUIRED` or `INPUT_REQUIRED`) is shown under `interactions/v1` and answered on the same task with `{ interactionId, approved }` or `{ interactionId, value }` under that URI in the message's `metadata`; text never approves. Artifacts carry the turn's output and the files it wrote, as `url` parts at `/v1/a2a/files/…` with `files/v1`; the task's metadata carries `progress/v1`, `telemetry/v1` and `effects/v1`. Extension data is answered only for the extensions activated with `A2A-Extensions`. A context is one session per subject, agent and `contextId`; a task is one turn. JSON-RPC errors are answered with 200; limits, scopes and unavailable streams stay HTTP errors. Not served: streaming, `GetExtendedAgentCard`.",
75
+ description: "A2A 1.0 JSON-RPC, for a subject, under the Nylorun profile v2 (Host feature `a2a-profile-v2`). `SendMessage` blocks up to the Runtime limit `a2aWaitMs` (5 minutes by default; then the task is answered still `WORKING`) unless `returnImmediately`; `GetTask` (with `historyLength`), `CancelTask` and `ListTasks`; and the four push notification config methods, plus `configuration.taskPushNotificationConfig` in `SendMessage`: each update is POSTed as one `StreamResponse`, signed with Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webhook-signature` with the Runtime's `a2a.push.secret`) and `X-A2A-Notification-Token`, at least once, retried for up to 24 hours, to hosts the Runtime allows (`a2a.push.allowHosts` for private ones). A message to a busy context is queued and answered with the task that will take it (`TASK_STATE_SUBMITTED`); `message.metadata.delivery: \"reject\"` asks for `UnsupportedOperationError` (reason `CONTEXT_BUSY`) instead. `message.metadata.removeTools` (Host feature `remove-tools`) names the tools a new message's turn may not use, as a session message's `removeTools`. A message is text, one data part, or text with `raw` files (stored as artifacts of the context's session) and `url` files (fetched by the Runtime), each at most the Runtime limit `inlineFileBytes` (20 MiB by default). An approval, question or connection the task waits for (`AUTH_REQUIRED` or `INPUT_REQUIRED`) is shown under `interactions/v1` and answered on the same task with `{ interactionId, approved }` or `{ interactionId, value }` under that URI in the message's `metadata`; text never approves. Artifacts carry the turn's output and the files it wrote, as `url` parts at `/v1/a2a/files/…` with `files/v1`; the task's metadata carries `progress/v1`, `telemetry/v1` and `effects/v1`. Extension data is answered only for the extensions activated with `A2A-Extensions`. A context is one session per subject, agent and `contextId`; a task is one turn. JSON-RPC errors are answered with 200; limits, scopes and unavailable streams stay HTTP errors. Not served: streaming, `GetExtendedAgentCard`.",
76
76
  externalDocs: A2A_SPECIFICATION,
77
77
  request: {
78
78
  params: agentId,
@@ -226,6 +226,12 @@ export interface SendParams {
226
226
  push?: PushConfigInput;
227
227
  /** `metadata.delivery`; default `queue`. */
228
228
  delivery: Delivery;
229
+ /**
230
+ * `metadata.removeTools` (Host feature `remove-tools`): the tools the message's turn may not
231
+ * use, by name, as a session message's `removeTools`. A new message only: a reply answers an
232
+ * interaction of a turn already running.
233
+ */
234
+ removeTools?: readonly string[];
229
235
  /** The answer the message carries under `interactions/v1`. */
230
236
  answer?: InteractionAnswer;
231
237
  }
@@ -223,6 +223,17 @@ export function parsePushConfig(value, field) {
223
223
  ...(authentication ? { authentication } : {}),
224
224
  };
225
225
  }
226
+ /** `metadata.removeTools`: at most 256 names of 1 to 256 characters (a session message's `removeTools`). */
227
+ function parseRemoveTools(metadata) {
228
+ const value = metadata.removeTools;
229
+ if (value === undefined || value === null)
230
+ return undefined;
231
+ if (!Array.isArray(value) ||
232
+ value.length > 256 ||
233
+ !value.every((name) => typeof name === "string" && name.length >= 1 && name.length <= 256))
234
+ return a2aFail("invalidParams", "message.metadata.removeTools must be at most 256 tool names of 1 to 256 characters", {}, "message.metadata.removeTools");
235
+ return value;
236
+ }
226
237
  /** `metadata.delivery`: `queue` (the default) or `reject`. */
227
238
  function parseDelivery(metadata) {
228
239
  const delivery = metadata.delivery;
@@ -272,6 +283,7 @@ export function parseSendParams(params) {
272
283
  // On the message (the profile's place), or on the request's own metadata.
273
284
  const delivery = parseDelivery(metadata.delivery === undefined && isObject(params.metadata) ? params.metadata : metadata);
274
285
  const answer = parseAnswer(metadata);
286
+ const removeTools = parseRemoveTools(metadata.removeTools === undefined && isObject(params.metadata) ? params.metadata : metadata);
275
287
  const configuration = params.configuration;
276
288
  if (configuration !== undefined && configuration !== null && !isObject(configuration))
277
289
  a2aFail("invalidParams", "configuration must be an object", {}, "configuration");
@@ -315,6 +327,7 @@ export function parseSendParams(params) {
315
327
  ...(historyLength !== undefined ? { historyLength } : {}),
316
328
  ...(push ? { push } : {}),
317
329
  delivery,
330
+ ...(removeTools ? { removeTools } : {}),
318
331
  ...(answer ? { answer } : {}),
319
332
  };
320
333
  }
@@ -335,6 +335,7 @@ async function sendMessage(caller, params, signal) {
335
335
  requestId: randomUUID(),
336
336
  idempotencyKey,
337
337
  ...body,
338
+ ...(send.removeTools ? { removeTools: [...send.removeTools] } : {}),
338
339
  }, async () => {
339
340
  const active = (await contextSession(caller, sessionId))?.activeTurnId;
340
341
  const taskId = active ? taskIdOf(context, active) : undefined;
@@ -214,6 +214,11 @@ export declare const AgentView: z.ZodObject<{
214
214
  versionBytes: z.ZodOptional<z.ZodNumber>;
215
215
  versionEntries: z.ZodOptional<z.ZodNumber>;
216
216
  }, z.core.$strict>>;
217
+ triggers: z.ZodOptional<z.ZodObject<{
218
+ count: z.ZodOptional<z.ZodNumber>;
219
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
220
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
221
+ }, z.core.$strict>>;
217
222
  }, z.core.$strict>>;
218
223
  secrets: z.ZodOptional<z.ZodLazy<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
219
224
  required: z.ZodOptional<z.ZodBoolean>;
@@ -379,6 +384,11 @@ export declare const AgentManifest: z.ZodObject<{
379
384
  versionBytes: z.ZodOptional<z.ZodNumber>;
380
385
  versionEntries: z.ZodOptional<z.ZodNumber>;
381
386
  }, z.core.$strict>>;
387
+ triggers: z.ZodOptional<z.ZodObject<{
388
+ count: z.ZodOptional<z.ZodNumber>;
389
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
390
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
391
+ }, z.core.$strict>>;
382
392
  }, z.core.$strict>>;
383
393
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
384
394
  required: z.ZodOptional<z.ZodBoolean>;
@@ -477,6 +487,11 @@ export declare const PutAgentManifestRequest: z.ZodObject<{
477
487
  versionBytes: z.ZodOptional<z.ZodNumber>;
478
488
  versionEntries: z.ZodOptional<z.ZodNumber>;
479
489
  }, z.core.$strict>>;
490
+ triggers: z.ZodOptional<z.ZodObject<{
491
+ count: z.ZodOptional<z.ZodNumber>;
492
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
493
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
494
+ }, z.core.$strict>>;
480
495
  }, z.core.$strict>>;
481
496
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
482
497
  required: z.ZodOptional<z.ZodBoolean>;
@@ -630,6 +645,11 @@ export declare const AgentManifestView: z.ZodObject<{
630
645
  versionBytes: z.ZodOptional<z.ZodNumber>;
631
646
  versionEntries: z.ZodOptional<z.ZodNumber>;
632
647
  }, z.core.$strict>>;
648
+ triggers: z.ZodOptional<z.ZodObject<{
649
+ count: z.ZodOptional<z.ZodNumber>;
650
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
651
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
652
+ }, z.core.$strict>>;
633
653
  }, z.core.$strict>>;
634
654
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
635
655
  required: z.ZodOptional<z.ZodBoolean>;
@@ -770,6 +790,11 @@ export declare const AgentManifestPlan: z.ZodObject<{
770
790
  versionBytes: z.ZodOptional<z.ZodNumber>;
771
791
  versionEntries: z.ZodOptional<z.ZodNumber>;
772
792
  }, z.core.$strict>>;
793
+ triggers: z.ZodOptional<z.ZodObject<{
794
+ count: z.ZodOptional<z.ZodNumber>;
795
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
796
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
797
+ }, z.core.$strict>>;
773
798
  }, z.core.$strict>>;
774
799
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
775
800
  required: z.ZodOptional<z.ZodBoolean>;
@@ -905,6 +930,11 @@ export declare const SaveAgentManifestResponse: z.ZodObject<{
905
930
  versionBytes: z.ZodOptional<z.ZodNumber>;
906
931
  versionEntries: z.ZodOptional<z.ZodNumber>;
907
932
  }, z.core.$strict>>;
933
+ triggers: z.ZodOptional<z.ZodObject<{
934
+ count: z.ZodOptional<z.ZodNumber>;
935
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
936
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
937
+ }, z.core.$strict>>;
908
938
  }, z.core.$strict>>;
909
939
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
910
940
  required: z.ZodOptional<z.ZodBoolean>;
@@ -1055,6 +1085,11 @@ export declare const ListAgentManifestsResponse: z.ZodObject<{
1055
1085
  versionBytes: z.ZodOptional<z.ZodNumber>;
1056
1086
  versionEntries: z.ZodOptional<z.ZodNumber>;
1057
1087
  }, z.core.$strict>>;
1088
+ triggers: z.ZodOptional<z.ZodObject<{
1089
+ count: z.ZodOptional<z.ZodNumber>;
1090
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
1091
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
1092
+ }, z.core.$strict>>;
1058
1093
  }, z.core.$strict>>;
1059
1094
  secrets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
1060
1095
  required: z.ZodOptional<z.ZodBoolean>;
@@ -1340,6 +1375,11 @@ export declare const ForkAgentResponse: z.ZodUnion<readonly [z.ZodObject<{
1340
1375
  versionBytes: z.ZodOptional<z.ZodNumber>;
1341
1376
  versionEntries: z.ZodOptional<z.ZodNumber>;
1342
1377
  }, z.core.$strict>>;
1378
+ triggers: z.ZodOptional<z.ZodObject<{
1379
+ count: z.ZodOptional<z.ZodNumber>;
1380
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
1381
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
1382
+ }, z.core.$strict>>;
1343
1383
  }, z.core.$strict>>;
1344
1384
  secrets: z.ZodOptional<z.ZodLazy<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
1345
1385
  required: z.ZodOptional<z.ZodBoolean>;
@@ -1613,6 +1653,11 @@ export declare const ListAgentsResponse: z.ZodObject<{
1613
1653
  versionBytes: z.ZodOptional<z.ZodNumber>;
1614
1654
  versionEntries: z.ZodOptional<z.ZodNumber>;
1615
1655
  }, z.core.$strict>>;
1656
+ triggers: z.ZodOptional<z.ZodObject<{
1657
+ count: z.ZodOptional<z.ZodNumber>;
1658
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
1659
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
1660
+ }, z.core.$strict>>;
1616
1661
  }, z.core.$strict>>;
1617
1662
  secrets: z.ZodOptional<z.ZodLazy<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
1618
1663
  required: z.ZodOptional<z.ZodBoolean>;
@@ -1724,9 +1769,12 @@ export declare const ListAgentEventsResponse: z.ZodObject<{
1724
1769
  "agent.running": "agent.running";
1725
1770
  "agent.start_failed": "agent.start_failed";
1726
1771
  "agent.suspended": "agent.suspended";
1772
+ "agent.trigger_created": "agent.trigger_created";
1773
+ "agent.trigger_deleted": "agent.trigger_deleted";
1727
1774
  "agent.trigger_paused": "agent.trigger_paused";
1728
1775
  "agent.trigger_resumed": "agent.trigger_resumed";
1729
1776
  "agent.trigger_secret_rotated": "agent.trigger_secret_rotated";
1777
+ "agent.trigger_updated": "agent.trigger_updated";
1730
1778
  "agent.version_changed": "agent.version_changed";
1731
1779
  }>;
1732
1780
  payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -2237,6 +2285,13 @@ export declare const TriggerList: z.ZodObject<{
2237
2285
  wake: "wake";
2238
2286
  webhook: "webhook";
2239
2287
  }>;
2288
+ origin: z.ZodEnum<{
2289
+ agent: "agent";
2290
+ manifest: "manifest";
2291
+ wake: "wake";
2292
+ }>;
2293
+ title: z.ZodNullable<z.ZodString>;
2294
+ createdSessionId: z.ZodNullable<z.ZodString>;
2240
2295
  status: z.ZodEnum<{
2241
2296
  active: "active";
2242
2297
  completed: "completed";
@@ -2251,6 +2306,7 @@ export declare const TriggerList: z.ZodObject<{
2251
2306
  lastRunAt: z.ZodNullable<z.ZodString>;
2252
2307
  webhookUrl: z.ZodOptional<z.ZodString>;
2253
2308
  secretSet: z.ZodOptional<z.ZodBoolean>;
2309
+ prompt: z.ZodOptional<z.ZodString>;
2254
2310
  }, z.core.$strict>>;
2255
2311
  }, z.core.$strict>;
2256
2312
  export declare const MemoryList: z.ZodObject<{
@@ -2345,6 +2401,69 @@ export declare const TriggerRunPage: z.ZodObject<{
2345
2401
  }, z.core.$strict>>;
2346
2402
  nextCursor: z.ZodNullable<z.ZodString>;
2347
2403
  }, z.core.$strict>;
2404
+ export declare const TenantRun: z.ZodObject<{
2405
+ runId: z.ZodString;
2406
+ agentId: z.ZodString;
2407
+ triggerId: z.ZodString;
2408
+ kind: z.ZodEnum<{
2409
+ at: "at";
2410
+ schedule: "schedule";
2411
+ wake: "wake";
2412
+ webhook: "webhook";
2413
+ }>;
2414
+ status: z.ZodEnum<{
2415
+ failed: "failed";
2416
+ queued: "queued";
2417
+ skipped: "skipped";
2418
+ started: "started";
2419
+ }>;
2420
+ reason: z.ZodNullable<z.ZodString>;
2421
+ sessionId: z.ZodNullable<z.ZodString>;
2422
+ turnId: z.ZodNullable<z.ZodString>;
2423
+ queuedMessageId: z.ZodNullable<z.ZodString>;
2424
+ dueAt: z.ZodString;
2425
+ firedAt: z.ZodString;
2426
+ late: z.ZodBoolean;
2427
+ origin: z.ZodEnum<{
2428
+ agent: "agent";
2429
+ manifest: "manifest";
2430
+ wake: "wake";
2431
+ }>;
2432
+ title: z.ZodNullable<z.ZodString>;
2433
+ }, z.core.$strict>;
2434
+ export declare const TenantRunEvent: z.ZodObject<{
2435
+ cursor: z.ZodString;
2436
+ run: z.ZodObject<{
2437
+ runId: z.ZodString;
2438
+ agentId: z.ZodString;
2439
+ triggerId: z.ZodString;
2440
+ kind: z.ZodEnum<{
2441
+ at: "at";
2442
+ schedule: "schedule";
2443
+ wake: "wake";
2444
+ webhook: "webhook";
2445
+ }>;
2446
+ status: z.ZodEnum<{
2447
+ failed: "failed";
2448
+ queued: "queued";
2449
+ skipped: "skipped";
2450
+ started: "started";
2451
+ }>;
2452
+ reason: z.ZodNullable<z.ZodString>;
2453
+ sessionId: z.ZodNullable<z.ZodString>;
2454
+ turnId: z.ZodNullable<z.ZodString>;
2455
+ queuedMessageId: z.ZodNullable<z.ZodString>;
2456
+ dueAt: z.ZodString;
2457
+ firedAt: z.ZodString;
2458
+ late: z.ZodBoolean;
2459
+ origin: z.ZodEnum<{
2460
+ agent: "agent";
2461
+ manifest: "manifest";
2462
+ wake: "wake";
2463
+ }>;
2464
+ title: z.ZodNullable<z.ZodString>;
2465
+ }, z.core.$strict>;
2466
+ }, z.core.$strict>;
2348
2467
  export declare const RunTriggerResponse: z.ZodObject<{
2349
2468
  run: z.ZodObject<{
2350
2469
  id: z.ZodString;
@@ -15243,6 +15362,7 @@ export declare const ToolPolicy: z.ZodObject<{
15243
15362
  kind: z.ZodOptional<z.ZodEnum<{
15244
15363
  http: "http";
15245
15364
  mcp: "mcp";
15365
+ runtime: "runtime";
15246
15366
  }>>;
15247
15367
  agent: z.ZodOptional<z.ZodString>;
15248
15368
  when: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -15271,6 +15391,7 @@ export declare const PutToolPolicyRequest: z.ZodObject<{
15271
15391
  kind: z.ZodOptional<z.ZodEnum<{
15272
15392
  http: "http";
15273
15393
  mcp: "mcp";
15394
+ runtime: "runtime";
15274
15395
  }>>;
15275
15396
  agent: z.ZodOptional<z.ZodString>;
15276
15397
  when: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -22167,6 +22288,11 @@ export declare const AgentPage: z.ZodObject<{
22167
22288
  versionBytes: z.ZodOptional<z.ZodNumber>;
22168
22289
  versionEntries: z.ZodOptional<z.ZodNumber>;
22169
22290
  }, z.core.$strict>>;
22291
+ triggers: z.ZodOptional<z.ZodObject<{
22292
+ count: z.ZodOptional<z.ZodNumber>;
22293
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
22294
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
22295
+ }, z.core.$strict>>;
22170
22296
  }, z.core.$strict>>;
22171
22297
  secrets: z.ZodOptional<z.ZodLazy<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
22172
22298
  required: z.ZodOptional<z.ZodBoolean>;
@@ -22355,6 +22481,11 @@ export declare const AgentPage: z.ZodObject<{
22355
22481
  versionBytes: z.ZodOptional<z.ZodNumber>;
22356
22482
  versionEntries: z.ZodOptional<z.ZodNumber>;
22357
22483
  }, z.core.$strict>>;
22484
+ triggers: z.ZodOptional<z.ZodObject<{
22485
+ count: z.ZodOptional<z.ZodNumber>;
22486
+ minIntervalMs: z.ZodOptional<z.ZodNumber>;
22487
+ runsPerHour: z.ZodOptional<z.ZodNumber>;
22488
+ }, z.core.$strict>>;
22358
22489
  }, z.core.$strict>>;
22359
22490
  secrets: z.ZodOptional<z.ZodLazy<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
22360
22491
  required: z.ZodOptional<z.ZodBoolean>;
@@ -5,7 +5,7 @@
5
5
  * global registry.
6
6
  */
7
7
  import { z } from "zod";
8
- import { PutSessionModelRequestSchema, SessionModelViewSchema, QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentFolderRequestSchema, AgentManifestSourceSchema, AgentManifestSourceDiffSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, TurnChangesPageSchema, TurnSummarySchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
8
+ import { PutSessionModelRequestSchema, SessionModelViewSchema, QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentFolderRequestSchema, AgentManifestSourceSchema, AgentManifestSourceDiffSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, TurnChangesPageSchema, TurnSummarySchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, TenantRunEventSchema, TenantRunSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
9
9
  function named(id, schema) {
10
10
  return schema.meta({ id });
11
11
  }
@@ -71,6 +71,8 @@ export const PutMemoryRequest = named("PutMemoryRequest", PutMemoryRequestSchema
71
71
  export const MemoryVersionPage = named("MemoryVersionPage", MemoryVersionPageSchema);
72
72
  export const MemoryVersionDetail = named("MemoryVersionDetail", MemoryVersionDetailSchema);
73
73
  export const TriggerRunPage = named("TriggerRunPage", TriggerRunPageSchema);
74
+ export const TenantRun = named("TenantRun", TenantRunSchema);
75
+ export const TenantRunEvent = named("TenantRunEvent", TenantRunEventSchema);
74
76
  export const RunTriggerResponse = named("RunTriggerResponse", RunTriggerResponseSchema);
75
77
  export const WebhookSecretResponse = named("WebhookSecretResponse", WebhookSecretResponseSchema);
76
78
  export const WebhookAcceptedResponse = named("WebhookAcceptedResponse", WebhookAcceptedResponseSchema);
@@ -19,6 +19,7 @@ import { agentManifestRoutes } from "./routes/agent-manifests.js";
19
19
  import { artifactRoutes } from "./routes/artifacts.js";
20
20
  import { readRoutes } from "./routes/reads.js";
21
21
  import { turnRoutes } from "./routes/turns.js";
22
+ import { runRoutes } from "./routes/runs.js";
22
23
  import { sessionRoutes } from "./routes/sessions.js";
23
24
  import { fileRoutes } from "./routes/files.js";
24
25
  import { keyRoutes } from "./routes/keys.js";
@@ -50,6 +51,7 @@ function build() {
50
51
  fileRoutes(api);
51
52
  agentRoutes(api);
52
53
  triggerRoutes(api);
54
+ runRoutes(api);
53
55
  memoryRoutes(api);
54
56
  webhookRoutes(api);
55
57
  agentManifestRoutes(api);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `GET /v1/runs/stream` (D83): the Tenant's runs stream, every run of every Agent's triggers as
3
+ * server-sent events from a cursor (`tenant/runs-stream.ts`). For an application credential that
4
+ * reads Agents; a run may arrive twice, and a reader drops a run id it has seen.
5
+ */
6
+ import type { OpenAPIHono } from "@hono/zod-openapi";
7
+ import type { TenantEnv } from "../app.js";
8
+ export declare function runRoutes(api: OpenAPIHono<TenantEnv>): void;
@@ -0,0 +1,30 @@
1
+ import { RESPONSE_ALREADY_SENT } from "@hono/node-server/utils/response";
2
+ import { z } from "zod";
3
+ import { TenantRunEvent } from "../../components.js";
4
+ import { streamRuns } from "../../../tenant/runs-stream.js";
5
+ import { requestCursor } from "../../../tenant/session-streams.js";
6
+ import { tenantRoute } from "../define.js";
7
+ const READ = { credentials: ["application"], scopes: ["agents:read", "agents:write"] };
8
+ export function runRoutes(api) {
9
+ tenantRoute(api, READ, {
10
+ method: "get",
11
+ path: "/v1/runs/stream",
12
+ tags: ["Triggers"],
13
+ summary: "Follow the Tenant's runs",
14
+ description: "Server-sent events, one `event: run` per run of any Agent's triggers, with its cursor as `id`, from the cursor on (`?cursor=` or `Last-Event-ID`; none reads from the oldest run the stream keeps, 7 days). The data is `{cursor, run}`: the run as the Agent's runs list it, with its Agent and its trigger's origin and title. A run may arrive twice: drop a `runId` you have seen. A cursor from before the Tenant's reset is refused (`cursor_expired`): read again without one. A `: keepalive` comment every 15 seconds.",
15
+ request: {
16
+ query: z.object({
17
+ cursor: z.string().optional().meta({ description: "The cursor of the last run read: the stream goes on after it" }),
18
+ }),
19
+ },
20
+ responses: {
21
+ 200: { description: "The runs", content: { "text/event-stream": { itemSchema: TenantRunEvent } } },
22
+ 400: { description: "Not a cursor of the runs stream (`invalid_cursor`)" },
23
+ 410: { description: "A cursor from before the Tenant's reset (`cursor_expired`)" },
24
+ },
25
+ }, async (c) => {
26
+ const url = new URL(c.req.url);
27
+ await streamRuns(c.env.tenant, c.env.incoming, c.env.outgoing, requestCursor(c.env.incoming, url));
28
+ return RESPONSE_ALREADY_SENT;
29
+ });
30
+ }
@@ -2,7 +2,8 @@
2
2
  * An Agent's triggers and their runs (track T4, D74): read them, pause and resume one, run one now
3
3
  * (keyed by `Idempotency-Key`), and page the runs; make a webhook trigger's signing secret, and
4
4
  * take a sender's delivery at its endpoint (D75), an anonymous, unversioned route. What a trigger is lives in the Agent's manifest
5
- * (`runtime.triggers`); these routes change only what the Agent owns, its status.
5
+ * (`runtime.triggers`), or, for one its agents made with the `triggers` tool (D83), on the Agent:
6
+ * these routes change only what the Agent owns, its status, and delete an agent's trigger.
6
7
  */
7
8
  import type { OpenAPIHono } from "@hono/zod-openapi";
8
9
  import type { TenantEnv } from "../app.js";
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { isAgentId } from "@nylorun/core/contracts";
3
- import { RunTriggerResponse, TriggerList, TriggerRunPage, WebhookAcceptedResponse, WebhookSecretResponse, } from "../../components.js";
3
+ import { DeletedResponse, RunTriggerResponse, TriggerList, TriggerRunPage, WebhookAcceptedResponse, WebhookSecretResponse, } from "../../components.js";
4
4
  import { assertReaches } from "../../../tenant/agents.js";
5
5
  import { fail } from "../../../tenant/http.js";
6
- import { listRuns, listTriggers, receiveWebhook, rotateWebhookSecret, runTriggerNow, setTriggerStatus, } from "../../../tenant/triggers.js";
6
+ import { deleteTrigger, listRuns, listTriggers, receiveWebhook, rotateWebhookSecret, runTriggerNow, setTriggerStatus, } from "../../../tenant/triggers.js";
7
7
  import { readRuntimeLimits } from "../../../tenant/runtime-limits.js";
8
8
  import { readBytes } from "../body.js";
9
9
  import { tenantRoute } from "../define.js";
@@ -25,8 +25,16 @@ const agentId = z.object({
25
25
  agentId: z.string().meta({ description: "The Agent id, percent-encoded" }),
26
26
  });
27
27
  const triggerPath = agentId.extend({
28
- triggerId: z.string().meta({ description: "The trigger's id in the manifest's `runtime.triggers`" }),
28
+ triggerId: z.string().meta({ description: "The trigger's id: in the manifest's `runtime.triggers`, or the one its agent gave it" }),
29
29
  });
30
+ /** Who a route call acts as, for the Agent's events: the principal (its subject), or the token's subject. */
31
+ function principalOf(scope) {
32
+ if (scope.kind === "token")
33
+ return `${scope.issuer}:${scope.subject}`;
34
+ if (scope.kind === "subject")
35
+ return `${scope.principalId}:${scope.subject}`;
36
+ return "principalId" in scope ? scope.principalId : undefined;
37
+ }
30
38
  function idOf(value) {
31
39
  if (!isAgentId(value))
32
40
  return fail(400, "An Agent id is up to 200 characters: /-separated segments of letters, digits, '.', '_' and '-'");
@@ -38,7 +46,7 @@ export function triggerRoutes(api) {
38
46
  path: "/v1/agents/{agentId}/triggers",
39
47
  tags: ["Triggers"],
40
48
  summary: "List an Agent's triggers",
41
- description: "Each trigger its manifest declares, with what the Agent holds of it: its status (`active`, `paused` with a reason, `completed` for an `at` that ran), when it runs next and last ran.",
49
+ description: "Each trigger its manifest declares, and each its agents made with the `triggers` tool (`origin: agent`, with the title and the session that made it), with what the Agent holds of it: its status (`active`, `paused` with a reason, `completed` for an `at` that ran), its prompt, when it runs next and last ran. A session's booked wake is not listed.",
42
50
  request: { params: agentId },
43
51
  responses: { 200: json(TriggerList, "The triggers") },
44
52
  }, async (c) => {
@@ -65,6 +73,26 @@ export function triggerRoutes(api) {
65
73
  assertReaches(c.get("scope"), id);
66
74
  return jsonResponse(200, await setTriggerStatus(c.env.tenant, id, c.req.param("triggerId"), action, originOf(c)));
67
75
  });
76
+ tenantRoute(api, WRITE, {
77
+ method: "delete",
78
+ path: "/v1/agents/{agentId}/triggers/{triggerId}",
79
+ tags: ["Triggers"],
80
+ summary: "Delete a trigger an agent made",
81
+ description: "Deletes a trigger one of the Agent's agents made with the `triggers` tool (`origin: agent`), with `agent.trigger_deleted` on the Agent's events; its runs stay. A trigger its manifest declares is refused (`trigger_from_manifest`): save a version without it, or pause it.",
82
+ request: { params: triggerPath },
83
+ responses: {
84
+ 200: json(DeletedResponse, "Deleted"),
85
+ 404: { description: "The Agent has no such trigger" },
86
+ 409: { description: "The manifest declares it (`trigger_from_manifest`)" },
87
+ },
88
+ }, async (c) => {
89
+ const id = idOf(c.req.param("agentId"));
90
+ const scope = c.get("scope");
91
+ assertReaches(scope, id);
92
+ const triggerId = c.req.param("triggerId");
93
+ await deleteTrigger(c.env.tenant, id, triggerId, principalOf(scope));
94
+ return jsonResponse(200, { id: triggerId });
95
+ });
68
96
  tenantRoute(api, WRITE, {
69
97
  method: "post",
70
98
  path: "/v1/agents/{agentId}/triggers/{triggerId}/run",
@@ -158,13 +158,15 @@ const RUNTIME_TAGS = [
158
158
  {
159
159
  name: "Triggers",
160
160
  group: "Agents",
161
- description: "What starts an Agent's turns with no client connected: the schedules, one-shot times and webhook endpoints its manifest's `runtime.triggers` declare. Each trigger's status is the Agent's: pause and resume it, run it now, make a webhook trigger's signing secret, and read its runs (`started`, `queued`, `skipped` or `failed`, with a reason). In `@nylorun/agents` and `nylorun agents triggers`.",
161
+ description: "What starts an Agent's turns with no client connected: the schedules, one-shot times and webhook endpoints its manifest's `runtime.triggers` declare, and the schedules and follow-ups its agents set up with the `triggers` tool (`engine.triggers`). Each trigger's status is the Agent's: pause and resume it, run it now, delete one an agent made, make a webhook trigger's signing secret, and read its runs (`started`, `queued`, `skipped` or `failed`, with a reason), an Agent's or the whole Tenant's as a stream. In `@nylorun/agents` and `nylorun agents triggers`.",
162
162
  operations: [
163
163
  "GET /v1/agents/{agentId}/triggers",
164
164
  "POST /v1/agents/{agentId}/triggers/{triggerId}/pause",
165
165
  "POST /v1/agents/{agentId}/triggers/{triggerId}/resume",
166
166
  "POST /v1/agents/{agentId}/triggers/{triggerId}/run",
167
+ "DELETE /v1/agents/{agentId}/triggers/{triggerId}",
167
168
  "GET /v1/agents/{agentId}/runs",
169
+ "GET /v1/runs/stream",
168
170
  "POST /v1/agents/{agentId}/triggers/{triggerId}/secret",
169
171
  "POST /v1/webhooks/{endpointId}",
170
172
  ],
@@ -16,7 +16,9 @@
16
16
  * for an agent covers the agents it uses as tools.
17
17
  *
18
18
  * A rule's `tool` matches the tool's identity (protocol 15): an MCP tool's own name on its
19
- * server (`server` names the server), an HTTP tool's declared name, a flow stage's key. The name
19
+ * server (`server` names the server), an HTTP tool's declared name, a flow stage's key, an
20
+ * operation the Runtime serves (`triggers`, `memory`, `schedule_wake`; D83), which only a rule of
21
+ * `kind: "runtime"` matches. The name
20
22
  * a harness gave the model never matches. A stored rule whose `tool` has `__` in it (an MCP tool
21
23
  * named by its old model-facing `server__tool` name) makes the policy unreadable, so every call
22
24
  * is refused until the policy names it by `server` and `tool`: a rule never silently stops
@@ -31,7 +33,7 @@ import type { Session } from "../tenant/context.js";
31
33
  export declare const TOOL_POLICY_SETTING = "tool-policy";
32
34
  /** A call as the policy reads it. */
33
35
  export interface PolicyCall {
34
- readonly kind: "mcp" | "http";
36
+ readonly kind: "mcp" | "http" | "runtime";
35
37
  /**
36
38
  * The tool's identity: an MCP tool's own name on its server, an HTTP tool's declared name, a
37
39
  * flow stage's key.
@@ -69,7 +71,7 @@ export declare function readToolPolicy(t: Pick<Tx, "getSetting">): Promise<ToolP
69
71
  * The decision for `request`, a session's MCP or HTTP tool call: the Tenant's rules and the
70
72
  * pinned manifest's `approval`. A policy that cannot be read refuses the call.
71
73
  */
72
- export declare function toolCallDecision(t: Pick<Tx, "getSetting">, s: Session, request: HostEffect, kind: "mcp" | "http"): Promise<PolicyDecision>;
74
+ export declare function toolCallDecision(t: Pick<Tx, "getSetting">, s: Session, request: HostEffect, kind: "mcp" | "http" | "runtime"): Promise<PolicyDecision>;
73
75
  /**
74
76
  * `request` as the policy reads it: by its target's identity (protocol 15), and by the agent that
75
77
  * calls it: an agent used as a tool by its id, with the session's root agent as its `root`, and
@@ -77,7 +79,7 @@ export declare function toolCallDecision(t: Pick<Tx, "getSetting">, s: Session,
77
79
  * session's Agent id (`s.agentId`), which protocol 16 made the Agent the session runs on
78
80
  * (`users/ada/desk` for the manifest `desk`).
79
81
  */
80
- export declare function policyCallOf(s: Pick<Session, "manifest">, request: HostEffect, kind: "mcp" | "http"): PolicyCall;
82
+ export declare function policyCallOf(s: Pick<Session, "manifest">, request: HostEffect, kind: "mcp" | "http" | "runtime"): PolicyCall;
81
83
  /** Decides `call` by `rules`; `pinnedAsk` adds the ask of a manifest saved before R5 step 2. */
82
84
  export declare function decide(rules: readonly ToolRule[], call: PolicyCall, pinnedAsk?: boolean): PolicyDecision;
83
85
  /**
@@ -16,7 +16,9 @@
16
16
  * for an agent covers the agents it uses as tools.
17
17
  *
18
18
  * A rule's `tool` matches the tool's identity (protocol 15): an MCP tool's own name on its
19
- * server (`server` names the server), an HTTP tool's declared name, a flow stage's key. The name
19
+ * server (`server` names the server), an HTTP tool's declared name, a flow stage's key, an
20
+ * operation the Runtime serves (`triggers`, `memory`, `schedule_wake`; D83), which only a rule of
21
+ * `kind: "runtime"` matches. The name
20
22
  * a harness gave the model never matches. A stored rule whose `tool` has `__` in it (an MCP tool
21
23
  * named by its old model-facing `server__tool` name) makes the policy unreadable, so every call
22
24
  * is refused until the policy names it by `server` and `tool`: a rule never silently stops
@@ -85,7 +87,9 @@ export function policyCallOf(s, request, kind) {
85
87
  kind,
86
88
  tool: target?.kind === "mcp" || target?.kind === "http"
87
89
  ? target.tool
88
- : (request.key ?? request.effectId),
90
+ : target?.kind === "runtime"
91
+ ? target.operation
92
+ : (request.key ?? request.effectId),
89
93
  ...(target?.kind === "mcp" ? { server: target.server } : {}),
90
94
  agent: request.agent?.id ?? s.manifest.id,
91
95
  ...(request.agent === undefined ? {} : { root: s.manifest.id }),
@@ -127,6 +131,10 @@ export function pinnedApproval(manifest, request) {
127
131
  function matches(rule, call) {
128
132
  if (rule.kind !== undefined && rule.kind !== call.kind)
129
133
  return false;
134
+ // A runtime operation matches only a rule that names kind `runtime` (D83): rules written for
135
+ // MCP and HTTP tools keep their meaning.
136
+ if (call.kind === "runtime" && rule.kind !== "runtime")
137
+ return false;
130
138
  if (rule.tool !== undefined && !glob(rule.tool).test(call.tool))
131
139
  return false;
132
140
  if (rule.server !== undefined && (call.server === undefined || !glob(rule.server).test(call.server)))