@openwop/spec-artifacts 2.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CORPUS-STAMP.json +234 -0
- package/LICENSE +201 -0
- package/README.md +7 -0
- package/api/.redocly.lint-ignore.yaml +22 -0
- package/api/asyncapi.yaml +834 -0
- package/api/grpc/openwop.proto +251 -0
- package/api/openapi.yaml +2693 -0
- package/api/redocly.yaml +23 -0
- package/api/seams-v2.yaml +680 -0
- package/api/v2/asyncapi.yaml +528 -0
- package/api/v2/openapi.yaml +3139 -0
- package/api/v2/redocly.yaml +16 -0
- package/package.json +10 -0
- package/schemas/README.md +144 -0
- package/schemas/a2a-task-state.schema.json +78 -0
- package/schemas/a2ui-surface-delta-frame.schema.json +48 -0
- package/schemas/agent-deployment-transition.schema.json +49 -0
- package/schemas/agent-deployment.schema.json +54 -0
- package/schemas/agent-eval-suite.schema.json +140 -0
- package/schemas/agent-inventory-response.schema.json +115 -0
- package/schemas/agent-manifest.schema.json +156 -0
- package/schemas/agent-org-chart.schema.json +82 -0
- package/schemas/agent-ref.schema.json +63 -0
- package/schemas/agent-roster-entry.schema.json +81 -0
- package/schemas/agent-roster-response.schema.json +21 -0
- package/schemas/ai-envelope.schema.json +134 -0
- package/schemas/annotation-create.schema.json +37 -0
- package/schemas/annotation.schema.json +56 -0
- package/schemas/artifact-type-pack-manifest.schema.json +244 -0
- package/schemas/audit-verify-result.schema.json +90 -0
- package/schemas/budget-policy.schema.json +18 -0
- package/schemas/capabilities.schema.json +4160 -0
- package/schemas/certification-bundle-v2.schema.json +118 -0
- package/schemas/channel-presence-payload.schema.json +41 -0
- package/schemas/channel-written-payload.schema.json +55 -0
- package/schemas/chat-card-pack-manifest.schema.json +253 -0
- package/schemas/compact-tool-descriptor.schema.json +51 -0
- package/schemas/compensation-policy.schema.json +64 -0
- package/schemas/conformance-certification-bundle.schema.json +86 -0
- package/schemas/connection-pack-manifest.schema.json +353 -0
- package/schemas/conversation-event.schema.json +168 -0
- package/schemas/conversation-turn.schema.json +117 -0
- package/schemas/core-conformance-mock-agent-config.schema.json +152 -0
- package/schemas/credential-provenance.schema.json +18 -0
- package/schemas/credential-reference.schema.json +21 -0
- package/schemas/debug-bundle.schema.json +196 -0
- package/schemas/dispatch-config.schema.json +112 -0
- package/schemas/envelopes/clarification.request.schema.json +52 -0
- package/schemas/envelopes/error.schema.json +30 -0
- package/schemas/envelopes/media.audio.schema.json +38 -0
- package/schemas/envelopes/media.file.schema.json +37 -0
- package/schemas/envelopes/media.image.schema.json +33 -0
- package/schemas/envelopes/schema.request.schema.json +26 -0
- package/schemas/envelopes/schema.response.schema.json +22 -0
- package/schemas/envelopes/ui.a2ui-surface.schema.json +154 -0
- package/schemas/error-envelope.schema.json +25 -0
- package/schemas/eval-summary.schema.json +92 -0
- package/schemas/export-bundle.schema.json +66 -0
- package/schemas/form-content-pack-manifest.schema.json +243 -0
- package/schemas/frontend-plugin-manifest.schema.json +109 -0
- package/schemas/goal.schema.json +104 -0
- package/schemas/heartbeat-evaluated.schema.json +14 -0
- package/schemas/heartbeat-state-changed.schema.json +14 -0
- package/schemas/localized-content-language-settings.schema.json +26 -0
- package/schemas/localized-content-page-response.schema.json +60 -0
- package/schemas/localized-content-page.schema.json +62 -0
- package/schemas/localized-content-section.schema.json +51 -0
- package/schemas/memory-entry.schema.json +36 -0
- package/schemas/memory-list-options.schema.json +37 -0
- package/schemas/node-pack-manifest.schema.json +654 -0
- package/schemas/orchestrator-decision.schema.json +90 -0
- package/schemas/org-chart-responsibility-view.schema.json +26 -0
- package/schemas/pack-lockfile.schema.json +108 -0
- package/schemas/prompt-kind.schema.json +8 -0
- package/schemas/prompt-pack-manifest.schema.json +117 -0
- package/schemas/prompt-ref.schema.json +40 -0
- package/schemas/prompt-template.schema.json +149 -0
- package/schemas/proposal.schema.json +84 -0
- package/schemas/registry-version-manifest.schema.json +208 -0
- package/schemas/residency.schema.json +16 -0
- package/schemas/run-ancestry-response.schema.json +54 -0
- package/schemas/run-diff-response.schema.json +64 -0
- package/schemas/run-event-payloads.schema.json +4452 -0
- package/schemas/run-event.schema.json +211 -0
- package/schemas/run-options.schema.json +80 -0
- package/schemas/run-orchestrator-decided-event.schema.json +20 -0
- package/schemas/run-snapshot.schema.json +148 -0
- package/schemas/security-advisory.schema.json +109 -0
- package/schemas/self-hosted-runner-dispatch-frame.schema.json +79 -0
- package/schemas/self-hosted-runner-registration.schema.json +53 -0
- package/schemas/self-hosted-runner-result-frame.schema.json +38 -0
- package/schemas/subject.schema.json +56 -0
- package/schemas/suspend-request.schema.json +207 -0
- package/schemas/tool-descriptor.schema.json +63 -0
- package/schemas/trigger-event.schema.json +222 -0
- package/schemas/trigger-subscription-registration.schema.json +67 -0
- package/schemas/trigger-subscription.schema.json +26 -0
- package/schemas/ui-plugin-message.schema.json +90 -0
- package/schemas/v2/a2a-task-state.schema.json +102 -0
- package/schemas/v2/a2ui-surface-delta-frame.schema.json +62 -0
- package/schemas/v2/agent-deployment-transition.schema.json +67 -0
- package/schemas/v2/agent-deployment.schema.json +68 -0
- package/schemas/v2/agent-eval-suite.schema.json +214 -0
- package/schemas/v2/agent-inventory-response.schema.json +172 -0
- package/schemas/v2/agent-manifest.schema.json +218 -0
- package/schemas/v2/agent-org-chart.schema.json +149 -0
- package/schemas/v2/agent-ref.schema.json +67 -0
- package/schemas/v2/agent-roster-entry.schema.json +104 -0
- package/schemas/v2/agent-roster-response.schema.json +27 -0
- package/schemas/v2/ai-envelope.schema.json +167 -0
- package/schemas/v2/annotation-create.schema.json +109 -0
- package/schemas/v2/annotation.schema.json +142 -0
- package/schemas/v2/artifact-type-pack-manifest.schema.json +245 -0
- package/schemas/v2/audit-verify-result.schema.json +110 -0
- package/schemas/v2/budget-policy.schema.json +61 -0
- package/schemas/v2/capabilities.schema.json +7644 -0
- package/schemas/v2/certification-bundle.schema.json +401 -0
- package/schemas/v2/channel-presence-payload.schema.json +60 -0
- package/schemas/v2/channel-written-payload.schema.json +64 -0
- package/schemas/v2/chat-card-pack-manifest.schema.json +254 -0
- package/schemas/v2/compact-tool-descriptor.schema.json +108 -0
- package/schemas/v2/compensation-policy.schema.json +91 -0
- package/schemas/v2/compensation-projection.schema.json +95 -0
- package/schemas/v2/configurable.schema.json +110 -0
- package/schemas/v2/connection-pack-manifest.schema.json +354 -0
- package/schemas/v2/conversation-event.schema.json +281 -0
- package/schemas/v2/conversation-turn.schema.json +165 -0
- package/schemas/v2/credential-provenance.schema.json +62 -0
- package/schemas/v2/credential-reference.schema.json +28 -0
- package/schemas/v2/debug-bundle.schema.json +312 -0
- package/schemas/v2/dispatch-config.schema.json +147 -0
- package/schemas/v2/effect-ledger-projection.schema.json +71 -0
- package/schemas/v2/effect-seam-manifest.schema.json +98 -0
- package/schemas/v2/envelopes/clarification.request.schema.json +59 -0
- package/schemas/v2/envelopes/error.schema.json +35 -0
- package/schemas/v2/envelopes/media.audio.schema.json +41 -0
- package/schemas/v2/envelopes/media.file.schema.json +40 -0
- package/schemas/v2/envelopes/media.image.schema.json +36 -0
- package/schemas/v2/envelopes/schema.request.schema.json +29 -0
- package/schemas/v2/envelopes/schema.response.schema.json +26 -0
- package/schemas/v2/envelopes/ui.a2ui-surface.schema.json +292 -0
- package/schemas/v2/error-envelope.schema.json +229 -0
- package/schemas/v2/eval-summary.schema.json +166 -0
- package/schemas/v2/export-bundle.schema.json +94 -0
- package/schemas/v2/form-content-pack-manifest.schema.json +241 -0
- package/schemas/v2/frontend-plugin-manifest.schema.json +152 -0
- package/schemas/v2/goal.schema.json +188 -0
- package/schemas/v2/heartbeat-evaluated.schema.json +34 -0
- package/schemas/v2/heartbeat-state-changed.schema.json +31 -0
- package/schemas/v2/ids.schema.json +31 -0
- package/schemas/v2/localized-content-language-settings.schema.json +34 -0
- package/schemas/v2/localized-content-page-response.schema.json +94 -0
- package/schemas/v2/localized-content-page.schema.json +87 -0
- package/schemas/v2/localized-content-section.schema.json +63 -0
- package/schemas/v2/memory-entry.schema.json +45 -0
- package/schemas/v2/memory-list-options.schema.json +41 -0
- package/schemas/v2/node-pack-manifest.schema.json +657 -0
- package/schemas/v2/orchestrator-decision.schema.json +120 -0
- package/schemas/v2/org-chart-responsibility-view.schema.json +36 -0
- package/schemas/v2/pack-lockfile.schema.json +139 -0
- package/schemas/v2/prompt-kind.schema.json +14 -0
- package/schemas/v2/prompt-pack-manifest.schema.json +118 -0
- package/schemas/v2/prompt-ref.schema.json +42 -0
- package/schemas/v2/prompt-template.schema.json +209 -0
- package/schemas/v2/proposal.schema.json +145 -0
- package/schemas/v2/registry-version-manifest.schema.json +292 -0
- package/schemas/v2/residency.schema.json +19 -0
- package/schemas/v2/run-ancestry-response.schema.json +68 -0
- package/schemas/v2/run-diff-response.schema.json +80 -0
- package/schemas/v2/run-event-payloads.schema.json +4588 -0
- package/schemas/v2/run-event.schema.json +324 -0
- package/schemas/v2/run-options.schema.json +90 -0
- package/schemas/v2/run-orchestrator-decided-event.schema.json +22 -0
- package/schemas/v2/run-snapshot.schema.json +207 -0
- package/schemas/v2/security-advisory.schema.json +138 -0
- package/schemas/v2/self-hosted-runner-dispatch-frame.schema.json +119 -0
- package/schemas/v2/self-hosted-runner-registration.schema.json +74 -0
- package/schemas/v2/self-hosted-runner-result-frame.schema.json +47 -0
- package/schemas/v2/subject-link.schema.json +69 -0
- package/schemas/v2/subject.schema.json +597 -0
- package/schemas/v2/suspend-request.schema.json +370 -0
- package/schemas/v2/tool-descriptor.schema.json +150 -0
- package/schemas/v2/trigger-event.schema.json +508 -0
- package/schemas/v2/trigger-subscription-registration.schema.json +99 -0
- package/schemas/v2/trigger-subscription.schema.json +79 -0
- package/schemas/v2/ui-plugin-message.schema.json +149 -0
- package/schemas/v2/workflow-chain-pack-manifest.schema.json +610 -0
- package/schemas/v2/workflow-definition.schema.json +864 -0
- package/schemas/v2/workload-identity.schema.json +115 -0
- package/schemas/v2/workspace-file-create.schema.json +23 -0
- package/schemas/v2/workspace-file.schema.json +45 -0
- package/schemas/workflow-chain-pack-manifest.schema.json +615 -0
- package/schemas/workflow-definition.schema.json +850 -0
- package/schemas/workload-identity.schema.json +79 -0
- package/schemas/workspace-file-create.schema.json +20 -0
- package/schemas/workspace-file.schema.json +39 -0
- package/spec/v1/alias-detectors.json +283 -0
- package/spec/v1/capability-declaration-classes.json +176 -0
- package/spec/v1/core-standard-manifest.json +423 -0
- package/spec/v1/deprecations.json +854 -0
- package/spec/v1/deprecations.schema.json +187 -0
- package/spec/v1/event-codemap.json +1089 -0
- package/spec/v1/event-codemap.schema.json +41 -0
- package/spec/v1/extensions.json +1273 -0
- package/spec/v1/gaps.json +14581 -0
- package/spec/v1/gaps.schema.json +55 -0
- package/spec/v1/migrations.json +1822 -0
- package/spec/v1/migrations.schema.json +44 -0
- package/spec/v1/operation-path-manifest.json +462 -0
- package/spec/v1/spec-gaps.json +4823 -0
- package/spec/v2/declaration.json +1862 -0
- package/spec/v2/declaration.schema.json +305 -0
- package/spec/v2/errors.json +837 -0
- package/spec/v2/event-codemap.json +1099 -0
- package/spec/v2/event-codemap.schema.json +114 -0
- package/spec/v2/ext/provider-idempotency/registry.json +6 -0
- package/spec/v2/facets/a2a.schema.json +51 -0
- package/spec/v2/facets/aiProviders.schema.json +56 -0
- package/spec/v2/facets/auth.schema.json +91 -0
- package/spec/v2/facets/heartbeat.schema.json +20 -0
- package/spec/v2/facets/interrupt.schema.json +29 -0
- package/spec/v2/facets/mcp.schema.json +81 -0
- package/spec/v2/facets/replay.schema.json +34 -0
- package/spec/v2/facets/sandbox.schema.json +31 -0
- package/spec/v2/facets/webhooks.schema.json +18 -0
- package/spec/v2/path-manifest.json +279 -0
- package/spec/v2/peer-dependency-aliases.json +165 -0
- package/spec/v2/profiles.json +45 -0
- package/spec/v2/release.json +6 -0
package/api/openapi.yaml
ADDED
|
@@ -0,0 +1,2693 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
|
|
3
|
+
info:
|
|
4
|
+
title: Workflow Orchestration Protocol (openwop) API
|
|
5
|
+
version: "1.1.0"
|
|
6
|
+
summary: REST surface for declaring, executing, suspending, resuming, and observing multi-step workflows.
|
|
7
|
+
description: |
|
|
8
|
+
Canonical OpenAPI 3.1 specification for openwop-compliant servers. Generated from `rest-endpoints.md` and references the JSON Schemas in `schemas/`.
|
|
9
|
+
|
|
10
|
+
See spec docs for semantics:
|
|
11
|
+
- `auth.md` — API key + scope vocabulary
|
|
12
|
+
- `idempotency.md` — `Idempotency-Key` header contract
|
|
13
|
+
- `version-negotiation.md` — `engineVersion` + `eventLogSchemaVersion`
|
|
14
|
+
- `capabilities.md` — `/.well-known/openwop` handshake
|
|
15
|
+
- `stream-modes.md` — SSE consumption modes
|
|
16
|
+
- `run-options.md` — `configurable`/`tags`/`metadata`
|
|
17
|
+
- `interrupt.md` — HITL primitive
|
|
18
|
+
- `replay.md` — `:fork` endpoint
|
|
19
|
+
|
|
20
|
+
**Registry scope (RFC 0094 §I).** This document specifies the HOST
|
|
21
|
+
surface. The production node-pack registry surface (`/v1/packs/*` —
|
|
22
|
+
publish/get/delete/sig, deprecation, yank, key rotation) is specified in
|
|
23
|
+
`spec/v1/node-packs.md` §"Registry HTTP API" + `spec/v1/registry-operations.md`
|
|
24
|
+
and is served by a registry service (e.g. the planned hosted reference
|
|
25
|
+
registry `packs.openwop.dev`, or a third-party/private registry
|
|
26
|
+
implementation) — a distinct deployable, out of scope for this host
|
|
27
|
+
OpenAPI document. Only the test-mode mirror (`/v1/packs-test/*`, RFC 0025)
|
|
28
|
+
is host-mounted and documented here.
|
|
29
|
+
contact:
|
|
30
|
+
name: openwop spec working group
|
|
31
|
+
url: https://openwop.dev/spec/v1/
|
|
32
|
+
license:
|
|
33
|
+
name: Apache-2.0
|
|
34
|
+
identifier: Apache-2.0
|
|
35
|
+
|
|
36
|
+
externalDocs:
|
|
37
|
+
description: openwop spec v1 corpus
|
|
38
|
+
url: https://openwop.dev/spec/v1/
|
|
39
|
+
|
|
40
|
+
servers:
|
|
41
|
+
# No `/v1` here: the version segment lives in the path keys below, so a
|
|
42
|
+
# server base carrying it too resolves every operation to `/v1/v1/*` and
|
|
43
|
+
# the unversioned discovery route to `/v1/.well-known/openwop` (RFC 0149 §A).
|
|
44
|
+
- url: https://{host}
|
|
45
|
+
description: openwop-compliant server
|
|
46
|
+
variables:
|
|
47
|
+
host:
|
|
48
|
+
default: api.example.com
|
|
49
|
+
description: Replace with your server's hostname.
|
|
50
|
+
|
|
51
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
52
|
+
# SECURITY
|
|
53
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
security:
|
|
55
|
+
- ApiKeyAuth: []
|
|
56
|
+
|
|
57
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
58
|
+
# TAGS
|
|
59
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
60
|
+
tags:
|
|
61
|
+
- name: discovery
|
|
62
|
+
description: Public capability + spec discovery (no auth required).
|
|
63
|
+
- name: workflows
|
|
64
|
+
description: Workflow definition manifest.
|
|
65
|
+
- name: runs
|
|
66
|
+
description: Run lifecycle — create, read, stream, cancel, fork.
|
|
67
|
+
- name: agents
|
|
68
|
+
description: Manifest-agent inventory (RFC 0072 §A). Read-only; gated on capabilities.agents.manifestRuntime. Dispatch rides the run surface (WorkflowNode.agent + POST /v1/runs).
|
|
69
|
+
- name: tools
|
|
70
|
+
description: Portable tool catalog (RFC 0078 §B). Read-only ToolDescriptor projection across tool sources (node-pack / workflow / mcp / connector / host-extension); gated on capabilities.toolCatalog; authorization-scoped per §F-2.
|
|
71
|
+
- name: hitl
|
|
72
|
+
description: Human-in-the-loop interrupts and approvals.
|
|
73
|
+
- name: artifacts
|
|
74
|
+
description: Run-produced artifacts.
|
|
75
|
+
- name: webhooks
|
|
76
|
+
description: Subscribe to run events via outbound HTTP.
|
|
77
|
+
- name: triggers
|
|
78
|
+
description: Durable trigger-bridge subscriptions (RFC 0083). RFC 0099 adds the external-event create surface (`POST /v1/trigger-subscriptions`); gated on `capabilities.triggerBridge.ingestion.registrationEndpoint`.
|
|
79
|
+
- name: audit
|
|
80
|
+
description: Audit-log integrity verification (gated on the `openwop-audit-log-integrity` profile).
|
|
81
|
+
- name: prompts
|
|
82
|
+
description: Prompt-template library — list, fetch, render, mutate (RFC 0028; gated on `capabilities.prompts.*`).
|
|
83
|
+
- name: content
|
|
84
|
+
description: Localized authored content — public delivery + tenant-scoped admin CRUD (RFC 0103; gated on `capabilities.content.supported`).
|
|
85
|
+
- name: host
|
|
86
|
+
description: Host-capability resources — e.g. the RFC 0059 agent workspace file store (gated on `capabilities.workspace.*`).
|
|
87
|
+
- name: packs-test
|
|
88
|
+
description: |
|
|
89
|
+
RFC 0025 (`Draft`). Test-mode mirror of the production `/v1/packs/*` publish/get/delete/sig surface against
|
|
90
|
+
an isolated catalog. Gated on `capabilities.packs.testMode.supported: true` plus the reference impl's
|
|
91
|
+
`OPENWOP_PACKS_TEST_NAMESPACE_ENABLED=true` env-gate. Lets the conformance suite exercise the documented
|
|
92
|
+
19-code publish error catalog without `packs:publish` scope on the real registry. Hosts that haven't
|
|
93
|
+
mounted this surface MUST return `404 Not Found` for every path under `/v1/packs-test/`.
|
|
94
|
+
|
|
95
|
+
Scope note (RFC 0094 §I): the PRODUCTION `/v1/packs/*` surface these paths mirror is specified in
|
|
96
|
+
`spec/v1/registry-operations.md` + `node-packs.md` §"Registry HTTP API" and is served by a registry
|
|
97
|
+
service (a distinct deployable from the host), so it is intentionally NOT defined in this host
|
|
98
|
+
OpenAPI document.
|
|
99
|
+
|
|
100
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
101
|
+
# PATHS
|
|
102
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
103
|
+
paths:
|
|
104
|
+
|
|
105
|
+
# ── Discovery (unauthenticated) ─────────────────────────────────────────
|
|
106
|
+
/.well-known/openwop:
|
|
107
|
+
get:
|
|
108
|
+
tags: [discovery]
|
|
109
|
+
summary: Capability declaration handshake.
|
|
110
|
+
operationId: getCapabilities
|
|
111
|
+
security: []
|
|
112
|
+
parameters:
|
|
113
|
+
- name: If-None-Match
|
|
114
|
+
in: header
|
|
115
|
+
required: false
|
|
116
|
+
schema: { type: string }
|
|
117
|
+
description: >-
|
|
118
|
+
RFC 0165 §C.2. Standard conditional request against the discovery document's `ETag`;
|
|
119
|
+
a matching value SHOULD yield `304 Not Modified`.
|
|
120
|
+
responses:
|
|
121
|
+
'200':
|
|
122
|
+
description: Capabilities object — see `capabilities.md`.
|
|
123
|
+
headers:
|
|
124
|
+
Cache-Control:
|
|
125
|
+
schema: { type: string }
|
|
126
|
+
example: 'public, max-age=300'
|
|
127
|
+
ETag:
|
|
128
|
+
schema: { type: string }
|
|
129
|
+
description: >-
|
|
130
|
+
RFC 0165 §C.2. Standard strong validator for the response bytes (SHOULD be sent).
|
|
131
|
+
Distinct from `Capabilities-Etag`, which validates negotiation safety
|
|
132
|
+
(`capabilities-change-detection.md` §"Cache validators").
|
|
133
|
+
Capabilities-Etag:
|
|
134
|
+
schema: { type: string }
|
|
135
|
+
description: Optional probe handle for mid-session capability change detection. Deprecated toward v2 (RFC 0165 §C.2).
|
|
136
|
+
content:
|
|
137
|
+
application/json:
|
|
138
|
+
schema:
|
|
139
|
+
$ref: '#/components/schemas/Capabilities'
|
|
140
|
+
'304':
|
|
141
|
+
description: RFC 0165 §C.2 — `If-None-Match` matched the current `ETag`; the body is unchanged.
|
|
142
|
+
'503':
|
|
143
|
+
description: Server unable to compute capabilities (transient).
|
|
144
|
+
content:
|
|
145
|
+
application/json:
|
|
146
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
147
|
+
|
|
148
|
+
/v1/openapi.json:
|
|
149
|
+
get:
|
|
150
|
+
tags: [discovery]
|
|
151
|
+
summary: Self-describing OpenAPI 3.1 spec.
|
|
152
|
+
operationId: getOpenApiSpec
|
|
153
|
+
security: []
|
|
154
|
+
responses:
|
|
155
|
+
'200':
|
|
156
|
+
description: This document.
|
|
157
|
+
content:
|
|
158
|
+
application/json:
|
|
159
|
+
schema:
|
|
160
|
+
type: object
|
|
161
|
+
'503':
|
|
162
|
+
description: Server unable to serve spec (transient).
|
|
163
|
+
content:
|
|
164
|
+
application/json:
|
|
165
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
166
|
+
|
|
167
|
+
# ── Workflows ───────────────────────────────────────────────────────────
|
|
168
|
+
/v1/workflows/{workflowId}:
|
|
169
|
+
get:
|
|
170
|
+
tags: [workflows]
|
|
171
|
+
summary: Read a workflow definition.
|
|
172
|
+
operationId: getWorkflow
|
|
173
|
+
parameters:
|
|
174
|
+
- $ref: '#/components/parameters/WorkflowId'
|
|
175
|
+
responses:
|
|
176
|
+
'200':
|
|
177
|
+
description: Workflow definition.
|
|
178
|
+
content:
|
|
179
|
+
application/json:
|
|
180
|
+
schema:
|
|
181
|
+
$ref: '../schemas/workflow-definition.schema.json'
|
|
182
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
183
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
184
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
185
|
+
|
|
186
|
+
# ── Runs ────────────────────────────────────────────────────────────────
|
|
187
|
+
/v1/runs:
|
|
188
|
+
post:
|
|
189
|
+
tags: [runs]
|
|
190
|
+
summary: Create a new run.
|
|
191
|
+
operationId: createRun
|
|
192
|
+
parameters:
|
|
193
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
194
|
+
- in: header
|
|
195
|
+
name: X-Dedup
|
|
196
|
+
schema:
|
|
197
|
+
type: string
|
|
198
|
+
enum: [enforce]
|
|
199
|
+
description: When set, server cross-host claim system rejects duplicate `(tenantId, scopeId)` pairs with `409 Conflict`.
|
|
200
|
+
- in: header
|
|
201
|
+
name: X-Force-Engine-Version
|
|
202
|
+
schema: { type: integer, minimum: 0 }
|
|
203
|
+
description: |
|
|
204
|
+
**Test-keys-only.** When set, the server emits events for this run AS IF it
|
|
205
|
+
were running the specified engine version (must be within the server's
|
|
206
|
+
advertised `Capabilities.testing.forceEngineVersionRange`). Used by the
|
|
207
|
+
conformance suite to verify version-negotiation fold-best-effort tolerance
|
|
208
|
+
across the spec's forward-compat matrix. Servers MUST reject on production
|
|
209
|
+
API keys with `403 force_engine_version_forbidden`. Closes F5.
|
|
210
|
+
requestBody:
|
|
211
|
+
required: true
|
|
212
|
+
content:
|
|
213
|
+
application/json:
|
|
214
|
+
schema:
|
|
215
|
+
# The body is the WorkflowId + inputs + transport-specific
|
|
216
|
+
# routing fields, plus the openwop RunOptions overlay (configurable,
|
|
217
|
+
# tags, metadata) hoisted into a first-class JSON Schema at
|
|
218
|
+
# ../schemas/run-options.schema.json. allOf composes the two
|
|
219
|
+
# so callers see one unified body shape. RFC 0094 §A: neither
|
|
220
|
+
# allOf branch is closed via additionalProperties (two closed
|
|
221
|
+
# branches inside one allOf made every documented body
|
|
222
|
+
# unsatisfiable); the composed request is closed here with
|
|
223
|
+
# `unevaluatedProperties: false` (JSON Schema 2020-12), so
|
|
224
|
+
# undeclared properties still fail at the composition level.
|
|
225
|
+
unevaluatedProperties: false
|
|
226
|
+
allOf:
|
|
227
|
+
- type: object
|
|
228
|
+
properties:
|
|
229
|
+
workflowId: { type: string, minLength: 1 }
|
|
230
|
+
inputs:
|
|
231
|
+
type: object
|
|
232
|
+
description: Workflow inputs (consumed by triggers/nodes).
|
|
233
|
+
residency:
|
|
234
|
+
# RFC 0129 — OPTIONAL data-residency constraint. Closed shape
|
|
235
|
+
# lives in the referenced schema (RFC 0094 §A forbids a closed
|
|
236
|
+
# `additionalProperties:false` branch inside this allOf; the
|
|
237
|
+
# $ref keeps the constraint out of the composition). A host
|
|
238
|
+
# advertising `capabilities.dataResidency` MUST honor-or-reject
|
|
239
|
+
# (accept iff region in advertised regions[], else
|
|
240
|
+
# `residency_unavailable`, create no run). Absent ⇒ no constraint.
|
|
241
|
+
$ref: '../schemas/residency.schema.json'
|
|
242
|
+
tenantId:
|
|
243
|
+
type: string
|
|
244
|
+
description: Tenant scoping. Server typically defaults from API key.
|
|
245
|
+
scopeId:
|
|
246
|
+
type: string
|
|
247
|
+
description: Opaque correlation ID for `X-Dedup` semantics.
|
|
248
|
+
callbackUrl:
|
|
249
|
+
type: string
|
|
250
|
+
format: uri
|
|
251
|
+
description: Signed-token HITL callback URL (see `interrupt.md`).
|
|
252
|
+
mode:
|
|
253
|
+
type: string
|
|
254
|
+
enum: [eval]
|
|
255
|
+
description: |
|
|
256
|
+
RFC 0081 §B. When `eval`, this run is an eval-suite projection
|
|
257
|
+
(not a workflow run): the host runs the `evalSuiteRef` against
|
|
258
|
+
`agentId`, emits the content-free `eval.*` family, and terminates
|
|
259
|
+
with an `EvalSummary` readable via `GET /v1/runs/{runId}/eval-summary`.
|
|
260
|
+
Capability-gated on `capabilities.agents.evalSuite.supported`; a
|
|
261
|
+
host that omits it rejects `mode: "eval"` with 501. Omit for a
|
|
262
|
+
normal workflow run.
|
|
263
|
+
evalSuiteRef:
|
|
264
|
+
type: string
|
|
265
|
+
minLength: 1
|
|
266
|
+
description: RFC 0081 — URI of the `AgentEvalSuite` to run. Required when mode is `eval`.
|
|
267
|
+
agentId:
|
|
268
|
+
type: string
|
|
269
|
+
minLength: 1
|
|
270
|
+
description: RFC 0081 — the manifest agent the eval suite targets. Required when mode is `eval`.
|
|
271
|
+
if:
|
|
272
|
+
properties: { mode: { const: eval } }
|
|
273
|
+
required: [mode]
|
|
274
|
+
then:
|
|
275
|
+
required: [evalSuiteRef, agentId]
|
|
276
|
+
else:
|
|
277
|
+
required: [workflowId]
|
|
278
|
+
- $ref: '../schemas/run-options.schema.json'
|
|
279
|
+
responses:
|
|
280
|
+
'201':
|
|
281
|
+
description: Run accepted.
|
|
282
|
+
headers:
|
|
283
|
+
openwop-Idempotent-Replay:
|
|
284
|
+
schema: { type: boolean }
|
|
285
|
+
description: Set when the response was served from the idempotency cache.
|
|
286
|
+
content:
|
|
287
|
+
application/json:
|
|
288
|
+
schema:
|
|
289
|
+
type: object
|
|
290
|
+
required: [runId, status, eventsUrl]
|
|
291
|
+
properties:
|
|
292
|
+
runId: { type: string }
|
|
293
|
+
status:
|
|
294
|
+
type: string
|
|
295
|
+
enum: [pending, running, waiting-approval, waiting-input, waiting-external]
|
|
296
|
+
eventsUrl: { type: string, format: uri }
|
|
297
|
+
statusUrl: { type: string, format: uri }
|
|
298
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
299
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
300
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
301
|
+
'409':
|
|
302
|
+
description: '`X-Dedup` collision OR concurrent `Idempotency-Key` collision.'
|
|
303
|
+
headers:
|
|
304
|
+
Retry-After:
|
|
305
|
+
schema: { type: integer }
|
|
306
|
+
description: Seconds until the active claim is stale-eligible.
|
|
307
|
+
content:
|
|
308
|
+
application/json:
|
|
309
|
+
schema:
|
|
310
|
+
$ref: '#/components/schemas/RunClaimConflict'
|
|
311
|
+
'429': { $ref: '#/components/responses/RateLimited' }
|
|
312
|
+
|
|
313
|
+
/v1/runs/{runId}:
|
|
314
|
+
get:
|
|
315
|
+
tags: [runs]
|
|
316
|
+
summary: Read run state (cached projection).
|
|
317
|
+
operationId: getRun
|
|
318
|
+
parameters:
|
|
319
|
+
- $ref: '#/components/parameters/RunId'
|
|
320
|
+
- in: header
|
|
321
|
+
name: If-None-Match
|
|
322
|
+
required: false
|
|
323
|
+
schema: { type: string }
|
|
324
|
+
description: |
|
|
325
|
+
RFC 0115. Conditional revalidation. When this carries the
|
|
326
|
+
current `ETag`, the host responds `304 Not Modified` with no
|
|
327
|
+
body (capability-gated on `restTransport.conditionalRunGet`).
|
|
328
|
+
responses:
|
|
329
|
+
'200':
|
|
330
|
+
description: Projected run state.
|
|
331
|
+
headers:
|
|
332
|
+
ETag:
|
|
333
|
+
schema: { type: string }
|
|
334
|
+
description: |
|
|
335
|
+
RFC 0115. Strong validator derived from the run's latest
|
|
336
|
+
persisted event-log sequence number; changes on every
|
|
337
|
+
observable state transition, stable while none occurs.
|
|
338
|
+
Content-Encoding:
|
|
339
|
+
required: false
|
|
340
|
+
schema: { type: string, enum: [gzip, br, zstd] }
|
|
341
|
+
description: |
|
|
342
|
+
RFC 0115. Present only when the host negotiated compression
|
|
343
|
+
from `Accept-Encoding`; pairs with `Vary: Accept-Encoding`.
|
|
344
|
+
The decoded body is byte-identical to the identity body.
|
|
345
|
+
content:
|
|
346
|
+
application/json:
|
|
347
|
+
schema:
|
|
348
|
+
$ref: '#/components/schemas/RunSnapshot'
|
|
349
|
+
'304':
|
|
350
|
+
description: 'RFC 0115. Not Modified — `If-None-Match` matched the current `ETag`. Empty body.'
|
|
351
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
352
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
353
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
354
|
+
|
|
355
|
+
/v1/runs/{runId}/events:
|
|
356
|
+
get:
|
|
357
|
+
tags: [runs]
|
|
358
|
+
summary: SSE stream of run events.
|
|
359
|
+
operationId: streamRunEvents
|
|
360
|
+
parameters:
|
|
361
|
+
- $ref: '#/components/parameters/RunId'
|
|
362
|
+
- in: query
|
|
363
|
+
name: streamMode
|
|
364
|
+
schema:
|
|
365
|
+
type: string
|
|
366
|
+
default: updates
|
|
367
|
+
pattern: '^(values|updates|messages|debug)(,(values|updates|messages|debug))*$'
|
|
368
|
+
description: |
|
|
369
|
+
Single mode: `values` / `updates` / `messages` / `debug`.
|
|
370
|
+
Mixed mode: comma-separated combination (e.g., `updates,messages`)
|
|
371
|
+
per S4 closure — server emits union-of-filters with per-event
|
|
372
|
+
`event:` field labeling which mode admitted each event.
|
|
373
|
+
`values` MUST NOT combine with other modes (state.snapshot semantics
|
|
374
|
+
need exclusive ownership). See `stream-modes.md`. Default `updates`.
|
|
375
|
+
- in: query
|
|
376
|
+
name: bufferMs
|
|
377
|
+
schema:
|
|
378
|
+
type: integer
|
|
379
|
+
minimum: 0
|
|
380
|
+
maximum: 5000
|
|
381
|
+
description: |
|
|
382
|
+
Optional batching hint per S3 closure. When set, the server
|
|
383
|
+
accumulates events for up to N ms (or until a forced-flush
|
|
384
|
+
trigger fires — terminal events, suspensions, connection close)
|
|
385
|
+
and emits a single SSE event with `event: batch` and `data:` as
|
|
386
|
+
a JSON array of `RunEventDoc`. Range 0..5000; `0` = no buffering.
|
|
387
|
+
See `stream-modes.md` §Aggregation hint.
|
|
388
|
+
- in: header
|
|
389
|
+
name: Last-Event-ID
|
|
390
|
+
schema: { type: string }
|
|
391
|
+
description: Resume from sequence after this ID.
|
|
392
|
+
responses:
|
|
393
|
+
'200':
|
|
394
|
+
description: SSE stream. Auto-closes on terminal event. Keep-alive comments every 30s.
|
|
395
|
+
content:
|
|
396
|
+
text/event-stream:
|
|
397
|
+
schema:
|
|
398
|
+
type: string
|
|
399
|
+
description: SSE events. Each event has `id:`, `event:`, `data:` per RFC 8895.
|
|
400
|
+
'400':
|
|
401
|
+
description: Unsupported `streamMode`.
|
|
402
|
+
content:
|
|
403
|
+
application/json:
|
|
404
|
+
schema:
|
|
405
|
+
$ref: '#/components/schemas/UnsupportedStreamMode'
|
|
406
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
407
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
408
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
409
|
+
|
|
410
|
+
/v1/runs/{runId}/events/poll:
|
|
411
|
+
get:
|
|
412
|
+
tags: [runs]
|
|
413
|
+
summary: Long-poll fallback for non-SSE clients.
|
|
414
|
+
operationId: pollRunEvents
|
|
415
|
+
parameters:
|
|
416
|
+
- $ref: '#/components/parameters/RunId'
|
|
417
|
+
- in: query
|
|
418
|
+
name: lastSequence
|
|
419
|
+
schema: { type: integer, minimum: 0 }
|
|
420
|
+
- in: query
|
|
421
|
+
name: timeout
|
|
422
|
+
schema: { type: integer, minimum: 1, maximum: 60, default: 30 }
|
|
423
|
+
description: Seconds to wait for new events. Max 60.
|
|
424
|
+
responses:
|
|
425
|
+
'200':
|
|
426
|
+
description: Events since `lastSequence`.
|
|
427
|
+
content:
|
|
428
|
+
application/json:
|
|
429
|
+
schema:
|
|
430
|
+
type: object
|
|
431
|
+
required: [events, isComplete]
|
|
432
|
+
properties:
|
|
433
|
+
events:
|
|
434
|
+
type: array
|
|
435
|
+
items:
|
|
436
|
+
$ref: '../schemas/run-event.schema.json'
|
|
437
|
+
isComplete: { type: boolean }
|
|
438
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
439
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
440
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
441
|
+
|
|
442
|
+
/v1/runs/{runId}/cancel:
|
|
443
|
+
post:
|
|
444
|
+
tags: [runs]
|
|
445
|
+
summary: Cancel an in-flight run.
|
|
446
|
+
operationId: cancelRun
|
|
447
|
+
parameters:
|
|
448
|
+
- $ref: '#/components/parameters/RunId'
|
|
449
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
450
|
+
requestBody:
|
|
451
|
+
content:
|
|
452
|
+
application/json:
|
|
453
|
+
schema:
|
|
454
|
+
type: object
|
|
455
|
+
properties:
|
|
456
|
+
reason: { type: string }
|
|
457
|
+
responses:
|
|
458
|
+
'200':
|
|
459
|
+
description: Run cancellation accepted (cascade may be async).
|
|
460
|
+
content:
|
|
461
|
+
application/json:
|
|
462
|
+
schema:
|
|
463
|
+
type: object
|
|
464
|
+
properties:
|
|
465
|
+
runId: { type: string }
|
|
466
|
+
status: { type: string, enum: [cancelled, cancelling] }
|
|
467
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
468
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
469
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
470
|
+
|
|
471
|
+
# ── Run feedback / annotations (RFC 0056) ────────────────────────────
|
|
472
|
+
# Gated on `capabilities.feedback.supported: true`. Annotations are a
|
|
473
|
+
# per-run side-resource (NOT replayable run-event-log entries); recording
|
|
474
|
+
# one also emits a live `run.annotated` SSE notification. Hosts without
|
|
475
|
+
# the advertised capability return `501 capability_not_provided`.
|
|
476
|
+
/v1/runs/{runId}/annotations:
|
|
477
|
+
post:
|
|
478
|
+
tags: [runs]
|
|
479
|
+
summary: Record a non-blocking quality annotation on a run (RFC 0056).
|
|
480
|
+
operationId: createAnnotation
|
|
481
|
+
parameters:
|
|
482
|
+
- $ref: '#/components/parameters/RunId'
|
|
483
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
484
|
+
requestBody:
|
|
485
|
+
required: true
|
|
486
|
+
content:
|
|
487
|
+
application/json:
|
|
488
|
+
schema:
|
|
489
|
+
$ref: '../schemas/annotation-create.schema.json'
|
|
490
|
+
responses:
|
|
491
|
+
'201':
|
|
492
|
+
description: Annotation recorded. Returns the persisted annotation.
|
|
493
|
+
content:
|
|
494
|
+
application/json:
|
|
495
|
+
schema:
|
|
496
|
+
$ref: '../schemas/annotation.schema.json'
|
|
497
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
498
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
499
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
500
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
501
|
+
'501':
|
|
502
|
+
description: 'Host does not advertise capabilities.feedback.supported (RFC 0056).'
|
|
503
|
+
content:
|
|
504
|
+
application/json:
|
|
505
|
+
schema:
|
|
506
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
507
|
+
get:
|
|
508
|
+
tags: [runs]
|
|
509
|
+
summary: List the annotations recorded on a run (RFC 0056).
|
|
510
|
+
operationId: listAnnotations
|
|
511
|
+
parameters:
|
|
512
|
+
- $ref: '#/components/parameters/RunId'
|
|
513
|
+
responses:
|
|
514
|
+
'200':
|
|
515
|
+
description: Annotations for the run (tenant-scoped).
|
|
516
|
+
content:
|
|
517
|
+
application/json:
|
|
518
|
+
schema:
|
|
519
|
+
type: object
|
|
520
|
+
required: [annotations]
|
|
521
|
+
properties:
|
|
522
|
+
annotations:
|
|
523
|
+
type: array
|
|
524
|
+
items:
|
|
525
|
+
$ref: '../schemas/annotation.schema.json'
|
|
526
|
+
additionalProperties: false
|
|
527
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
528
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
529
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
530
|
+
'501':
|
|
531
|
+
description: 'Host does not advertise capabilities.feedback.supported (RFC 0056).'
|
|
532
|
+
content:
|
|
533
|
+
application/json:
|
|
534
|
+
schema:
|
|
535
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
536
|
+
|
|
537
|
+
# ── External-event trigger subscriptions (RFC 0099) ──────────────────
|
|
538
|
+
# Gated on `capabilities.triggerBridge.ingestion.registrationEndpoint: true`.
|
|
539
|
+
# The portable create surface for an external-event (webhook/email/form)
|
|
540
|
+
# subscription that binds a source to a workflow to start. Returns the
|
|
541
|
+
# created TriggerSubscription (RFC 0083 §B) plus a source-specific binding
|
|
542
|
+
# (ingest URL/address + secret fingerprint), returned once at creation.
|
|
543
|
+
# Hosts without the advertised capability return `501 capability_not_provided`.
|
|
544
|
+
/v1/trigger-subscriptions:
|
|
545
|
+
post:
|
|
546
|
+
tags: [triggers]
|
|
547
|
+
summary: Register an external-event trigger subscription (RFC 0099).
|
|
548
|
+
description: |
|
|
549
|
+
Creates an external-event (`webhook`/`email`/`form`) TriggerSubscription
|
|
550
|
+
bound to a workflow, with a dedup config and a source-authenticity
|
|
551
|
+
verification policy (RFC 0099 §F.2). The `workflowId` MUST resolve under
|
|
552
|
+
the caller's RFC 0048 owner triple. The response carries the created
|
|
553
|
+
TriggerSubscription plus a source-specific `binding`; the binding
|
|
554
|
+
secret/URL is returned ONCE and is not re-fetchable in cleartext.
|
|
555
|
+
operationId: createTriggerSubscription
|
|
556
|
+
parameters:
|
|
557
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
558
|
+
requestBody:
|
|
559
|
+
required: true
|
|
560
|
+
content:
|
|
561
|
+
application/json:
|
|
562
|
+
schema:
|
|
563
|
+
$ref: '../schemas/trigger-subscription-registration.schema.json'
|
|
564
|
+
responses:
|
|
565
|
+
'201':
|
|
566
|
+
description: Subscription created. Returns the TriggerSubscription + a source-specific binding.
|
|
567
|
+
content:
|
|
568
|
+
application/json:
|
|
569
|
+
schema:
|
|
570
|
+
type: object
|
|
571
|
+
required: [subscription, binding]
|
|
572
|
+
additionalProperties: false
|
|
573
|
+
properties:
|
|
574
|
+
subscription:
|
|
575
|
+
$ref: '../schemas/trigger-subscription.schema.json'
|
|
576
|
+
binding:
|
|
577
|
+
type: object
|
|
578
|
+
description: |
|
|
579
|
+
Source-specific binding the caller needs to wire the external
|
|
580
|
+
source. For `webhook`: `{ ingestUrl, secretFingerprint }`; for
|
|
581
|
+
`email`: `{ ingestAddress }`; for `form`: `{ ingestUrl }`. The
|
|
582
|
+
secret is returned once at creation (SR-1).
|
|
583
|
+
additionalProperties: true
|
|
584
|
+
properties:
|
|
585
|
+
ingestUrl: { type: string, format: uri }
|
|
586
|
+
ingestAddress: { type: string }
|
|
587
|
+
secretFingerprint: { type: string, maxLength: 32 }
|
|
588
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
589
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
590
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
591
|
+
'501':
|
|
592
|
+
description: 'Host does not advertise capabilities.triggerBridge.ingestion.registrationEndpoint (RFC 0099).'
|
|
593
|
+
content:
|
|
594
|
+
application/json:
|
|
595
|
+
schema:
|
|
596
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
597
|
+
|
|
598
|
+
# ── Localized content surface (RFC 0103) ─────────────────────────────
|
|
599
|
+
# Public, cacheable delivery + tenant-scoped admin CRUD for authored
|
|
600
|
+
# localized content (pages → sections). Locale on the public path is
|
|
601
|
+
# negotiated via `Accept-Language` per the Stable i18n.md annex (no
|
|
602
|
+
# `?locale=`); admin writes target a locale in the body. Gated on
|
|
603
|
+
# `capabilities.content.supported: true` (requires `i18n.supported`).
|
|
604
|
+
# Hosts without the capability return `501 capability_not_provided`.
|
|
605
|
+
/v1/content/pages/{slug}:
|
|
606
|
+
get:
|
|
607
|
+
tags: [content]
|
|
608
|
+
# Public delivery: anonymous-capable, cacheable. Tenant is host-resolved
|
|
609
|
+
# (credential-derived when authenticated; host-defined when anonymous,
|
|
610
|
+
# localized-content.md §F). Clears global ApiKeyAuth like getCapabilities.
|
|
611
|
+
security: []
|
|
612
|
+
summary: Deliver a published content page resolved for the negotiated locale (RFC 0103 §D).
|
|
613
|
+
description: |
|
|
614
|
+
Resolves the published page `slug` for the locale negotiated from
|
|
615
|
+
`Accept-Language` (i18n.md fallback: q-value order → language family →
|
|
616
|
+
`content.baseLocale`), applies the per-section field merge
|
|
617
|
+
(`localized-content.md` §C), and returns the already-merged sections in
|
|
618
|
+
render order. Sets `Content-Language` to the locale used,
|
|
619
|
+
`Vary: Accept-Language, Accept-Encoding`, and
|
|
620
|
+
`Cache-Control: public, max-age=300, stale-while-revalidate=3600`.
|
|
621
|
+
Serves `status: "published"` content only. Tenant is host-resolved
|
|
622
|
+
(`localized-content.md` §F): credential-derived when authenticated,
|
|
623
|
+
host-defined (e.g. domain) when anonymous. A `slug` absent for the
|
|
624
|
+
resolved tenant returns the same `404` as a nonexistent slug (no
|
|
625
|
+
cross-tenant enumeration).
|
|
626
|
+
operationId: getContentPage
|
|
627
|
+
parameters:
|
|
628
|
+
- name: slug
|
|
629
|
+
in: path
|
|
630
|
+
required: true
|
|
631
|
+
schema: { type: string, pattern: '^[a-z][a-z0-9-]*$' }
|
|
632
|
+
description: The page slug.
|
|
633
|
+
- name: Accept-Language
|
|
634
|
+
in: header
|
|
635
|
+
required: false
|
|
636
|
+
schema: { type: string }
|
|
637
|
+
description: BCP-47 preference list; authoritative for locale selection (i18n.md). A malformed value MUST NOT 400.
|
|
638
|
+
responses:
|
|
639
|
+
'200':
|
|
640
|
+
description: The resolved, published page for the negotiated locale.
|
|
641
|
+
headers:
|
|
642
|
+
Content-Language:
|
|
643
|
+
schema: { type: string }
|
|
644
|
+
description: The BCP-47 locale actually used (equals the response `locale`).
|
|
645
|
+
content:
|
|
646
|
+
application/json:
|
|
647
|
+
schema:
|
|
648
|
+
$ref: '../schemas/localized-content-page-response.schema.json'
|
|
649
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
650
|
+
'501':
|
|
651
|
+
description: 'Host does not advertise capabilities.content.supported (RFC 0103).'
|
|
652
|
+
content:
|
|
653
|
+
application/json:
|
|
654
|
+
schema:
|
|
655
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
656
|
+
|
|
657
|
+
/v1/content/pages:
|
|
658
|
+
get:
|
|
659
|
+
tags: [content]
|
|
660
|
+
summary: List content pages for the caller's tenant (RFC 0103 §D, admin).
|
|
661
|
+
description: |
|
|
662
|
+
Tenant-scoped admin listing of pages (draft + published). Requires a
|
|
663
|
+
principal with `content.read` scope.
|
|
664
|
+
operationId: listContentPages
|
|
665
|
+
responses:
|
|
666
|
+
'200':
|
|
667
|
+
description: The caller-tenant's pages.
|
|
668
|
+
content:
|
|
669
|
+
application/json:
|
|
670
|
+
schema:
|
|
671
|
+
type: array
|
|
672
|
+
items:
|
|
673
|
+
$ref: '../schemas/localized-content-page.schema.json'
|
|
674
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
675
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
676
|
+
'501':
|
|
677
|
+
description: 'Host does not advertise capabilities.content.supported (RFC 0103).'
|
|
678
|
+
content:
|
|
679
|
+
application/json:
|
|
680
|
+
schema:
|
|
681
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
682
|
+
post:
|
|
683
|
+
tags: [content]
|
|
684
|
+
summary: Create a content page (RFC 0103 §D, admin).
|
|
685
|
+
description: Tenant-scoped page creation. Requires `content.write` scope.
|
|
686
|
+
operationId: createContentPage
|
|
687
|
+
requestBody:
|
|
688
|
+
required: true
|
|
689
|
+
content:
|
|
690
|
+
application/json:
|
|
691
|
+
schema:
|
|
692
|
+
$ref: '../schemas/localized-content-page.schema.json'
|
|
693
|
+
responses:
|
|
694
|
+
'201':
|
|
695
|
+
description: The created page.
|
|
696
|
+
content:
|
|
697
|
+
application/json:
|
|
698
|
+
schema:
|
|
699
|
+
$ref: '../schemas/localized-content-page.schema.json'
|
|
700
|
+
'400':
|
|
701
|
+
description: 'Invalid request (e.g. baseLocale in supportedLocales, or a malformed locale/slug).'
|
|
702
|
+
content:
|
|
703
|
+
application/json:
|
|
704
|
+
schema:
|
|
705
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
706
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
707
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
708
|
+
|
|
709
|
+
/v1/content/pages/{pageId}/sections/{sectionId}:
|
|
710
|
+
put:
|
|
711
|
+
tags: [content]
|
|
712
|
+
summary: Upsert a section's base or per-locale fields (RFC 0103 §D, admin).
|
|
713
|
+
description: |
|
|
714
|
+
Locale-targeted write: `locale == content.baseLocale` upserts the
|
|
715
|
+
section's base `data`; any other (BCP-47-subset) locale upserts
|
|
716
|
+
`localizations[locale]`. Tenant-scoped; requires `content.write`.
|
|
717
|
+
operationId: putContentSection
|
|
718
|
+
parameters:
|
|
719
|
+
- name: pageId
|
|
720
|
+
in: path
|
|
721
|
+
required: true
|
|
722
|
+
schema: { type: string, minLength: 1 }
|
|
723
|
+
- name: sectionId
|
|
724
|
+
in: path
|
|
725
|
+
required: true
|
|
726
|
+
schema: { type: string, minLength: 1 }
|
|
727
|
+
requestBody:
|
|
728
|
+
required: true
|
|
729
|
+
content:
|
|
730
|
+
application/json:
|
|
731
|
+
schema:
|
|
732
|
+
type: object
|
|
733
|
+
additionalProperties: false
|
|
734
|
+
required: [locale, data]
|
|
735
|
+
properties:
|
|
736
|
+
locale:
|
|
737
|
+
type: string
|
|
738
|
+
pattern: '^[a-z]{2}(-[A-Z]{2})?$'
|
|
739
|
+
description: Target locale; baseLocale upserts `data`, else `localizations[locale]`.
|
|
740
|
+
data:
|
|
741
|
+
type: object
|
|
742
|
+
additionalProperties: true
|
|
743
|
+
description: The field overlay for the target locale.
|
|
744
|
+
responses:
|
|
745
|
+
'200':
|
|
746
|
+
description: The updated section record.
|
|
747
|
+
content:
|
|
748
|
+
application/json:
|
|
749
|
+
schema:
|
|
750
|
+
$ref: '../schemas/localized-content-section.schema.json'
|
|
751
|
+
'400':
|
|
752
|
+
description: 'Invalid request (e.g. baseLocale in supportedLocales, or a malformed locale/slug).'
|
|
753
|
+
content:
|
|
754
|
+
application/json:
|
|
755
|
+
schema:
|
|
756
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
757
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
758
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
759
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
760
|
+
|
|
761
|
+
/v1/content/settings:
|
|
762
|
+
get:
|
|
763
|
+
tags: [content]
|
|
764
|
+
summary: Read the tenant's content language settings (RFC 0103 §B, admin).
|
|
765
|
+
description: Tenant-scoped read of `{ baseLocale, supportedLocales, autoTranslateOnPublish }`. Requires `content.read`.
|
|
766
|
+
operationId: getContentSettings
|
|
767
|
+
responses:
|
|
768
|
+
'200':
|
|
769
|
+
description: The tenant's language settings.
|
|
770
|
+
content:
|
|
771
|
+
application/json:
|
|
772
|
+
schema:
|
|
773
|
+
$ref: '../schemas/localized-content-language-settings.schema.json'
|
|
774
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
775
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
776
|
+
'501':
|
|
777
|
+
description: 'Host does not advertise capabilities.content.supported (RFC 0103).'
|
|
778
|
+
content:
|
|
779
|
+
application/json:
|
|
780
|
+
schema:
|
|
781
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
782
|
+
put:
|
|
783
|
+
tags: [content]
|
|
784
|
+
summary: Update the tenant's content language settings (RFC 0103 §B, admin).
|
|
785
|
+
description: |
|
|
786
|
+
Tenant-scoped settings update. The invariant `baseLocale ∉
|
|
787
|
+
supportedLocales` MUST hold (else `400`). Requires `content.write`.
|
|
788
|
+
operationId: putContentSettings
|
|
789
|
+
requestBody:
|
|
790
|
+
required: true
|
|
791
|
+
content:
|
|
792
|
+
application/json:
|
|
793
|
+
schema:
|
|
794
|
+
$ref: '../schemas/localized-content-language-settings.schema.json'
|
|
795
|
+
responses:
|
|
796
|
+
'200':
|
|
797
|
+
description: The updated language settings.
|
|
798
|
+
content:
|
|
799
|
+
application/json:
|
|
800
|
+
schema:
|
|
801
|
+
$ref: '../schemas/localized-content-language-settings.schema.json'
|
|
802
|
+
'400':
|
|
803
|
+
description: 'Invalid request (e.g. baseLocale in supportedLocales, or a malformed locale/slug).'
|
|
804
|
+
content:
|
|
805
|
+
application/json:
|
|
806
|
+
schema:
|
|
807
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
808
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
809
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
810
|
+
|
|
811
|
+
# ── Durable A2A task read seam (RFC 0100) ────────────────────────────
|
|
812
|
+
# Host-extension convenience read of the persisted A2ATaskState projection
|
|
813
|
+
# (RFC 0100 §2). The NORMATIVE A2A surface stays the A2A `tasks/get`
|
|
814
|
+
# JSON-RPC method per A2A v0.3 — this is a non-normative host-extension
|
|
815
|
+
# name under `/v1/host/sample/*`. Gated on `capabilities.a2a.durableTasks`.
|
|
816
|
+
/v1/host/sample/a2a/tasks/{taskId}:
|
|
817
|
+
get:
|
|
818
|
+
tags: [host]
|
|
819
|
+
summary: Read the persisted durable A2A task projection (RFC 0100, host-extension).
|
|
820
|
+
description: |
|
|
821
|
+
Returns the persisted `A2ATaskState` for `taskId` (== the backing
|
|
822
|
+
`runId`) per RFC 0100 §2 — a host-extension convenience read of the
|
|
823
|
+
durable projection that survives caller disconnect. The normative A2A
|
|
824
|
+
read surface remains the A2A `tasks/get` JSON-RPC method. Hosts that do
|
|
825
|
+
not advertise `capabilities.a2a.durableTasks` return `501`.
|
|
826
|
+
operationId: getA2ATaskState
|
|
827
|
+
parameters:
|
|
828
|
+
- name: taskId
|
|
829
|
+
in: path
|
|
830
|
+
required: true
|
|
831
|
+
schema: { type: string, minLength: 1 }
|
|
832
|
+
description: The A2A Task.id (equals the backing OpenWOP runId).
|
|
833
|
+
responses:
|
|
834
|
+
'200':
|
|
835
|
+
description: The persisted durable A2A task projection.
|
|
836
|
+
content:
|
|
837
|
+
application/json:
|
|
838
|
+
schema:
|
|
839
|
+
$ref: '../schemas/a2a-task-state.schema.json'
|
|
840
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
841
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
842
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
843
|
+
'501':
|
|
844
|
+
description: 'Host does not advertise capabilities.a2a.durableTasks (RFC 0100).'
|
|
845
|
+
content:
|
|
846
|
+
application/json:
|
|
847
|
+
schema:
|
|
848
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
849
|
+
|
|
850
|
+
# ── Agent workspace files (RFC 0059) ─────────────────────────────────
|
|
851
|
+
# Gated on `capabilities.workspace.supported: true`. A versioned,
|
|
852
|
+
# tenant·workspace-scoped (RFC 0048) ground-truth file store with atomic,
|
|
853
|
+
# optimistically-concurrent (`If-Match`) writes. A successful PUT/DELETE
|
|
854
|
+
# emits a content-free `workspace.updated` event. Hosts without the
|
|
855
|
+
# advertised capability return `501 capability_not_provided`.
|
|
856
|
+
/v1/host/workspace/files:
|
|
857
|
+
get:
|
|
858
|
+
tags: [host]
|
|
859
|
+
summary: List workspace file metadata for the caller's tenant·workspace (RFC 0059).
|
|
860
|
+
description: |
|
|
861
|
+
Returns file metadata (no bodies) for the caller's `{tenant,
|
|
862
|
+
workspace}` per RFC 0059 §C. Optional `?prefix=` filters the flat
|
|
863
|
+
`path` namespace to entries starting with the given prefix.
|
|
864
|
+
operationId: listWorkspaceFiles
|
|
865
|
+
parameters:
|
|
866
|
+
- $ref: '#/components/parameters/WorkspacePrefix'
|
|
867
|
+
responses:
|
|
868
|
+
'200':
|
|
869
|
+
description: Workspace file metadata (tenant·workspace-scoped; bodies omitted).
|
|
870
|
+
content:
|
|
871
|
+
application/json:
|
|
872
|
+
schema:
|
|
873
|
+
type: object
|
|
874
|
+
required: [files]
|
|
875
|
+
properties:
|
|
876
|
+
files:
|
|
877
|
+
type: array
|
|
878
|
+
items:
|
|
879
|
+
$ref: '../schemas/workspace-file.schema.json'
|
|
880
|
+
additionalProperties: false
|
|
881
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
882
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
883
|
+
'501':
|
|
884
|
+
description: 'Host does not advertise capabilities.workspace.supported (RFC 0059).'
|
|
885
|
+
content:
|
|
886
|
+
application/json:
|
|
887
|
+
schema:
|
|
888
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
889
|
+
|
|
890
|
+
/v1/host/workspace/files/{path}:
|
|
891
|
+
get:
|
|
892
|
+
tags: [host]
|
|
893
|
+
summary: Read one workspace file (RFC 0059).
|
|
894
|
+
description: |
|
|
895
|
+
Returns the `WorkspaceFile` at `path` for the caller's `{tenant,
|
|
896
|
+
workspace}`. When `capabilities.workspace.versioned: true`, an
|
|
897
|
+
optional `?version=N` returns the historical snapshot at version N.
|
|
898
|
+
operationId: getWorkspaceFile
|
|
899
|
+
parameters:
|
|
900
|
+
- $ref: '#/components/parameters/WorkspacePath'
|
|
901
|
+
- $ref: '#/components/parameters/WorkspaceVersion'
|
|
902
|
+
responses:
|
|
903
|
+
'200':
|
|
904
|
+
description: The workspace file (current version, or `?version=N` when versioned).
|
|
905
|
+
content:
|
|
906
|
+
application/json:
|
|
907
|
+
schema:
|
|
908
|
+
$ref: '../schemas/workspace-file.schema.json'
|
|
909
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
910
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
911
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
912
|
+
'501':
|
|
913
|
+
description: 'Host does not advertise capabilities.workspace.supported (RFC 0059).'
|
|
914
|
+
content:
|
|
915
|
+
application/json:
|
|
916
|
+
schema:
|
|
917
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
918
|
+
put:
|
|
919
|
+
tags: [host]
|
|
920
|
+
summary: Atomic create/replace of a workspace file (RFC 0059).
|
|
921
|
+
description: |
|
|
922
|
+
Atomically creates or replaces the file at `path` per RFC 0059 §C.
|
|
923
|
+
MUST honor `If-Match: <etag>` — a stale token returns `409
|
|
924
|
+
workspace_conflict` (`details.currentVersion` carries the live
|
|
925
|
+
version). On success the host bumps `version`, recomputes `etag`,
|
|
926
|
+
and emits a `workspace.updated` event. A `content` exceeding
|
|
927
|
+
`capabilities.workspace.maxFileBytes` returns `workspace_too_large`.
|
|
928
|
+
operationId: putWorkspaceFile
|
|
929
|
+
parameters:
|
|
930
|
+
- $ref: '#/components/parameters/WorkspacePath'
|
|
931
|
+
- $ref: '#/components/parameters/IfMatch'
|
|
932
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
933
|
+
requestBody:
|
|
934
|
+
required: true
|
|
935
|
+
content:
|
|
936
|
+
application/json:
|
|
937
|
+
schema:
|
|
938
|
+
$ref: '../schemas/workspace-file-create.schema.json'
|
|
939
|
+
responses:
|
|
940
|
+
'200':
|
|
941
|
+
description: File created or replaced. Returns the persisted WorkspaceFile.
|
|
942
|
+
content:
|
|
943
|
+
application/json:
|
|
944
|
+
schema:
|
|
945
|
+
$ref: '../schemas/workspace-file.schema.json'
|
|
946
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
947
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
948
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
949
|
+
'409':
|
|
950
|
+
description: 'Stale `If-Match` — the file changed since the supplied etag (`workspace_conflict`).'
|
|
951
|
+
content:
|
|
952
|
+
application/json:
|
|
953
|
+
schema:
|
|
954
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
955
|
+
'413':
|
|
956
|
+
description: 'Content exceeds `capabilities.workspace.maxFileBytes` (`workspace_too_large`).'
|
|
957
|
+
content:
|
|
958
|
+
application/json:
|
|
959
|
+
schema:
|
|
960
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
961
|
+
'501':
|
|
962
|
+
description: 'Host does not advertise capabilities.workspace.supported (RFC 0059).'
|
|
963
|
+
content:
|
|
964
|
+
application/json:
|
|
965
|
+
schema:
|
|
966
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
967
|
+
delete:
|
|
968
|
+
tags: [host]
|
|
969
|
+
summary: Delete a workspace file (RFC 0059).
|
|
970
|
+
description: |
|
|
971
|
+
Removes the file at `path` (and, when `versioned: true`, writes a
|
|
972
|
+
tombstone). Emits a `workspace.updated` event on success.
|
|
973
|
+
operationId: deleteWorkspaceFile
|
|
974
|
+
parameters:
|
|
975
|
+
- $ref: '#/components/parameters/WorkspacePath'
|
|
976
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
977
|
+
responses:
|
|
978
|
+
'204':
|
|
979
|
+
description: File deleted.
|
|
980
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
981
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
982
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
983
|
+
'501':
|
|
984
|
+
description: 'Host does not advertise capabilities.workspace.supported (RFC 0059).'
|
|
985
|
+
content:
|
|
986
|
+
application/json:
|
|
987
|
+
schema:
|
|
988
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
989
|
+
|
|
990
|
+
/v1/runs:bulk-cancel:
|
|
991
|
+
post:
|
|
992
|
+
tags: [runs]
|
|
993
|
+
summary: Cancel a set of in-flight runs in a single request.
|
|
994
|
+
description: |
|
|
995
|
+
Per `spec/v1/rest-endpoints.md` §"POST /v1/runs:bulk-cancel". Accepts
|
|
996
|
+
a non-empty array of runIds and processes each cancellation
|
|
997
|
+
independently. Returns `200` with a per-id results array even when
|
|
998
|
+
some individual cancellations fail; the top-level operation succeeds
|
|
999
|
+
when the request reached the host, regardless of per-id outcomes.
|
|
1000
|
+
Hosts enforce a host-defined cap on the array length (RECOMMENDED
|
|
1001
|
+
100); over-cap requests return `400 validation_error`.
|
|
1002
|
+
operationId: bulkCancelRuns
|
|
1003
|
+
parameters:
|
|
1004
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1005
|
+
requestBody:
|
|
1006
|
+
required: true
|
|
1007
|
+
content:
|
|
1008
|
+
application/json:
|
|
1009
|
+
schema:
|
|
1010
|
+
type: object
|
|
1011
|
+
required: [runIds]
|
|
1012
|
+
properties:
|
|
1013
|
+
runIds:
|
|
1014
|
+
type: array
|
|
1015
|
+
minItems: 1
|
|
1016
|
+
maxItems: 100
|
|
1017
|
+
items: { type: string, minLength: 1, maxLength: 128 }
|
|
1018
|
+
reason: { type: string, maxLength: 512 }
|
|
1019
|
+
additionalProperties: false
|
|
1020
|
+
responses:
|
|
1021
|
+
'200':
|
|
1022
|
+
description: Per-id cancel results.
|
|
1023
|
+
content:
|
|
1024
|
+
application/json:
|
|
1025
|
+
schema:
|
|
1026
|
+
type: object
|
|
1027
|
+
required: [results]
|
|
1028
|
+
properties:
|
|
1029
|
+
results:
|
|
1030
|
+
type: array
|
|
1031
|
+
items:
|
|
1032
|
+
type: object
|
|
1033
|
+
required: [runId, ok]
|
|
1034
|
+
properties:
|
|
1035
|
+
runId: { type: string, minLength: 1 }
|
|
1036
|
+
ok: { type: boolean }
|
|
1037
|
+
status: { type: string, enum: [cancelled, cancelling] }
|
|
1038
|
+
error:
|
|
1039
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
1040
|
+
additionalProperties: false
|
|
1041
|
+
additionalProperties: false
|
|
1042
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
1043
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1044
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1045
|
+
|
|
1046
|
+
/v1/runs/{runId}:fork:
|
|
1047
|
+
post:
|
|
1048
|
+
tags: [runs]
|
|
1049
|
+
summary: Fork the run for replay or branch (see `replay.md`).
|
|
1050
|
+
operationId: forkRun
|
|
1051
|
+
parameters:
|
|
1052
|
+
- $ref: '#/components/parameters/RunId'
|
|
1053
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1054
|
+
requestBody:
|
|
1055
|
+
required: true
|
|
1056
|
+
content:
|
|
1057
|
+
application/json:
|
|
1058
|
+
schema:
|
|
1059
|
+
type: object
|
|
1060
|
+
required: [mode]
|
|
1061
|
+
properties:
|
|
1062
|
+
fromSeq:
|
|
1063
|
+
type: integer
|
|
1064
|
+
minimum: 0
|
|
1065
|
+
description: |
|
|
1066
|
+
Inclusive — events `< fromSeq` are fixed history; `>= fromSeq` are re-executed.
|
|
1067
|
+
Required for `branch` (the branch point). Optional for `replay`; when omitted,
|
|
1068
|
+
defaults to `0` (full re-execution from source-run start) per `replay.md`
|
|
1069
|
+
§"Replay-mode defaults".
|
|
1070
|
+
mode:
|
|
1071
|
+
type: string
|
|
1072
|
+
enum: [replay, branch]
|
|
1073
|
+
runOptionsOverlay:
|
|
1074
|
+
type: object
|
|
1075
|
+
description: For `branch` mode only — caller-supplied `RunOptions` to overlay.
|
|
1076
|
+
additionalProperties: false
|
|
1077
|
+
responses:
|
|
1078
|
+
'201':
|
|
1079
|
+
description: Fork accepted, new run started.
|
|
1080
|
+
content:
|
|
1081
|
+
application/json:
|
|
1082
|
+
schema:
|
|
1083
|
+
type: object
|
|
1084
|
+
required: [runId, sourceRunId, mode, status, eventsUrl]
|
|
1085
|
+
properties:
|
|
1086
|
+
runId: { type: string }
|
|
1087
|
+
sourceRunId: { type: string }
|
|
1088
|
+
fromSeq: { type: integer }
|
|
1089
|
+
mode: { type: string, enum: [replay, branch] }
|
|
1090
|
+
status: { type: string }
|
|
1091
|
+
eventsUrl: { type: string, format: uri }
|
|
1092
|
+
'400':
|
|
1093
|
+
description: Invalid `fromSeq`, `replay` with non-empty `runOptionsOverlay`, etc.
|
|
1094
|
+
content:
|
|
1095
|
+
application/json:
|
|
1096
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1097
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1098
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1099
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
1100
|
+
'422':
|
|
1101
|
+
description: "`fromSeq` references a sequence number that doesn't exist in the source run's event log."
|
|
1102
|
+
content:
|
|
1103
|
+
application/json:
|
|
1104
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1105
|
+
/v1/runs/{runId}/ancestry:
|
|
1106
|
+
get:
|
|
1107
|
+
tags: [runs]
|
|
1108
|
+
summary: |
|
|
1109
|
+
RFC 0040 §C — return the run's immediate parent in the cross-host
|
|
1110
|
+
composition chain. Capability-gated on
|
|
1111
|
+
`capabilities.multiAgent.executionModel.crossHostCausation.ancestryEndpointSupported: true`;
|
|
1112
|
+
hosts that don't advertise return 404 not_found. Clients walk the full
|
|
1113
|
+
chain by following `parent.wellKnownUrl` per response, one hop at a
|
|
1114
|
+
time.
|
|
1115
|
+
operationId: getRunAncestry
|
|
1116
|
+
parameters:
|
|
1117
|
+
- $ref: '#/components/parameters/RunId'
|
|
1118
|
+
responses:
|
|
1119
|
+
'200':
|
|
1120
|
+
description: |
|
|
1121
|
+
Run's immediate parent (or `parent: null` for top-level runs).
|
|
1122
|
+
content:
|
|
1123
|
+
application/json:
|
|
1124
|
+
schema:
|
|
1125
|
+
$ref: '../schemas/run-ancestry-response.schema.json'
|
|
1126
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1127
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1128
|
+
'404':
|
|
1129
|
+
description: |
|
|
1130
|
+
Either the run doesn't exist, OR the host doesn't advertise
|
|
1131
|
+
`crossHostCausation.ancestryEndpointSupported: true` and treats
|
|
1132
|
+
the endpoint as absent. Clients can disambiguate by inspecting
|
|
1133
|
+
the host's discovery doc.
|
|
1134
|
+
content:
|
|
1135
|
+
application/json:
|
|
1136
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1137
|
+
|
|
1138
|
+
/v1/agents:
|
|
1139
|
+
get:
|
|
1140
|
+
tags: [agents]
|
|
1141
|
+
summary: |
|
|
1142
|
+
RFC 0072 §A — list the manifest agents this host has installed into its
|
|
1143
|
+
AgentRegistry (RFC 0070). Capability-gated on
|
|
1144
|
+
`capabilities.agents.manifestRuntime.supported: true`; hosts that don't
|
|
1145
|
+
advertise it return 404. Read-only projection — never carries the
|
|
1146
|
+
system-prompt body, resolved handoff schemas, or credential material (SR-1).
|
|
1147
|
+
Dispatch is not a bespoke endpoint: a manifest agent is invoked as a run
|
|
1148
|
+
whose node pins it via `WorkflowNode.agent` + `POST /v1/runs` (RFC 0072 §B).
|
|
1149
|
+
RFC 0074 — the result is scoped to the authenticated principal's owner
|
|
1150
|
+
triple (RFC 0048). When `capabilities.agents.manifestRuntime.installScope`
|
|
1151
|
+
is `'tenant'`, only the agents available to the caller's tenant·workspace
|
|
1152
|
+
are returned (an agent another workspace installed is absent, never
|
|
1153
|
+
disclosed); when `'host'` (default) the inventory is host-global as in
|
|
1154
|
+
RFC 0072. A `'tenant'`-scoped host MUST reject unauthenticated/unscoped
|
|
1155
|
+
requests per its standard auth contract rather than fall back to a global list.
|
|
1156
|
+
operationId: listAgents
|
|
1157
|
+
responses:
|
|
1158
|
+
'200':
|
|
1159
|
+
description: Installed manifest agents (agentId-sorted).
|
|
1160
|
+
content:
|
|
1161
|
+
application/json:
|
|
1162
|
+
schema:
|
|
1163
|
+
$ref: '../schemas/agent-inventory-response.schema.json'
|
|
1164
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1165
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1166
|
+
'404':
|
|
1167
|
+
description: |
|
|
1168
|
+
Host does not advertise `capabilities.agents.manifestRuntime` and
|
|
1169
|
+
treats the endpoint as absent.
|
|
1170
|
+
content:
|
|
1171
|
+
application/json:
|
|
1172
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1173
|
+
|
|
1174
|
+
/v1/agents/{agentId}:
|
|
1175
|
+
get:
|
|
1176
|
+
tags: [agents]
|
|
1177
|
+
summary: |
|
|
1178
|
+
RFC 0072 §A — return one installed manifest agent's inventory entry, or
|
|
1179
|
+
404 when no such agent is installed (or the host doesn't advertise
|
|
1180
|
+
`capabilities.agents.manifestRuntime`). RFC 0074 — resolved within the
|
|
1181
|
+
authenticated principal's owner triple (RFC 0048): on an
|
|
1182
|
+
`installScope: 'tenant'` host an agent the caller's workspace has not
|
|
1183
|
+
approved 404s identically to "not installed", so the surface never
|
|
1184
|
+
discloses another tenant's inventory.
|
|
1185
|
+
operationId: getAgent
|
|
1186
|
+
parameters:
|
|
1187
|
+
- in: path
|
|
1188
|
+
name: agentId
|
|
1189
|
+
required: true
|
|
1190
|
+
schema: { type: string, pattern: '^(?!roster$|org-chart$).+$' }
|
|
1191
|
+
description: |
|
|
1192
|
+
The manifest agentId. MUST NOT be the reserved literals `roster` or
|
|
1193
|
+
`org-chart` — those name the sibling collection routes
|
|
1194
|
+
(`/v1/agents/roster`, `/v1/agents/org-chart`), so excluding them here
|
|
1195
|
+
keeps `/v1/agents/{agentId}` unambiguous against them.
|
|
1196
|
+
responses:
|
|
1197
|
+
'200':
|
|
1198
|
+
description: The agent's inventory entry.
|
|
1199
|
+
content:
|
|
1200
|
+
application/json:
|
|
1201
|
+
schema:
|
|
1202
|
+
$ref: '../schemas/agent-inventory-response.schema.json#/$defs/AgentInventoryEntry'
|
|
1203
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1204
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1205
|
+
'404':
|
|
1206
|
+
description: No such agent, or the host doesn't advertise the capability.
|
|
1207
|
+
content:
|
|
1208
|
+
application/json:
|
|
1209
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1210
|
+
|
|
1211
|
+
/v1/agents/{agentId}/deployments:
|
|
1212
|
+
get:
|
|
1213
|
+
tags: [agents]
|
|
1214
|
+
summary: |
|
|
1215
|
+
RFC 0082 §C/§E — list the deployment records (per-(agentId, version)) for
|
|
1216
|
+
a manifest agent: the lifecycle `state`, the named `channels`, the canary
|
|
1217
|
+
share, the rollback pointer, and the last-transition provenance. Read-only,
|
|
1218
|
+
content-free of any manifest body or credential (SR-1). Capability-gated on
|
|
1219
|
+
`capabilities.agents.deployment.supported: true`; hosts that don't advertise
|
|
1220
|
+
it return 404. Tenant-scoped to the caller's owner triple (RFC 0048/0074)
|
|
1221
|
+
when `installScope: 'tenant'`.
|
|
1222
|
+
operationId: listAgentDeployments
|
|
1223
|
+
parameters:
|
|
1224
|
+
- in: path
|
|
1225
|
+
name: agentId
|
|
1226
|
+
required: true
|
|
1227
|
+
schema: { type: string, pattern: '^(?!roster$|org-chart$).+$' }
|
|
1228
|
+
description: |
|
|
1229
|
+
The manifest agentId. MUST NOT be the reserved literals `roster` or
|
|
1230
|
+
`org-chart` — those name the sibling collection routes
|
|
1231
|
+
(`/v1/agents/roster/{rosterId}`, `/v1/agents/org-chart/{departmentId}`),
|
|
1232
|
+
so excluding them here keeps `/v1/agents/{agentId}/deployments`
|
|
1233
|
+
unambiguous against them.
|
|
1234
|
+
responses:
|
|
1235
|
+
'200':
|
|
1236
|
+
description: The agent's deployment records (version-sorted).
|
|
1237
|
+
content:
|
|
1238
|
+
application/json:
|
|
1239
|
+
schema:
|
|
1240
|
+
type: array
|
|
1241
|
+
items: { $ref: '../schemas/agent-deployment.schema.json' }
|
|
1242
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1243
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1244
|
+
'404':
|
|
1245
|
+
description: No such agent, or the host doesn't advertise `capabilities.agents.deployment`.
|
|
1246
|
+
content:
|
|
1247
|
+
application/json:
|
|
1248
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1249
|
+
post:
|
|
1250
|
+
tags: [agents]
|
|
1251
|
+
summary: |
|
|
1252
|
+
RFC 0082 §E — request a deployment state transition (promote / pause /
|
|
1253
|
+
deprecate / rollback / adjust-canary). The host MUST authorize fail-closed
|
|
1254
|
+
against the RFC 0049 `deploy:*` scope (absent/unseeded role denies), run any
|
|
1255
|
+
configured RFC 0051 approvalGate, and — when the gate carries `requiredEval`
|
|
1256
|
+
— verify the referenced RFC 0081 eval run is terminal and `EvalSummary.passed`
|
|
1257
|
+
BEFORE emitting `deployment.promoted`. On success returns the updated
|
|
1258
|
+
deployment record and emits the matching content-free `deployment.*` event.
|
|
1259
|
+
operationId: transitionAgentDeployment
|
|
1260
|
+
parameters:
|
|
1261
|
+
- in: path
|
|
1262
|
+
name: agentId
|
|
1263
|
+
required: true
|
|
1264
|
+
schema: { type: string }
|
|
1265
|
+
description: The manifest agentId.
|
|
1266
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1267
|
+
requestBody:
|
|
1268
|
+
required: true
|
|
1269
|
+
content:
|
|
1270
|
+
application/json:
|
|
1271
|
+
schema:
|
|
1272
|
+
$ref: '../schemas/agent-deployment-transition.schema.json'
|
|
1273
|
+
responses:
|
|
1274
|
+
'200':
|
|
1275
|
+
description: The deployment record after the applied transition.
|
|
1276
|
+
content:
|
|
1277
|
+
application/json:
|
|
1278
|
+
schema:
|
|
1279
|
+
$ref: '../schemas/agent-deployment.schema.json'
|
|
1280
|
+
'400':
|
|
1281
|
+
description: |
|
|
1282
|
+
Validation error, or a transition that the host's advertised
|
|
1283
|
+
`states`/`canary` cannot satisfy, or `no_active_deployment` when a
|
|
1284
|
+
referenced channel resolves to no active version.
|
|
1285
|
+
content:
|
|
1286
|
+
application/json:
|
|
1287
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1288
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1289
|
+
'403':
|
|
1290
|
+
description: |
|
|
1291
|
+
Fail-closed authorization denial (the principal lacks the required
|
|
1292
|
+
`deploy:*` scope — RFC 0049), or `eval_gate_unmet` when a `requiredEval`
|
|
1293
|
+
gate's referenced eval run is not terminal-and-passed (RFC 0081).
|
|
1294
|
+
content:
|
|
1295
|
+
application/json:
|
|
1296
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1297
|
+
'404':
|
|
1298
|
+
description: No such agent, or the host doesn't advertise `capabilities.agents.deployment`.
|
|
1299
|
+
content:
|
|
1300
|
+
application/json:
|
|
1301
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1302
|
+
|
|
1303
|
+
/v1/agents/roster:
|
|
1304
|
+
get:
|
|
1305
|
+
tags: [agents]
|
|
1306
|
+
summary: |
|
|
1307
|
+
RFC 0086 §B — list the standing agent roster (named "digital-twin
|
|
1308
|
+
employee" instances + their workflow portfolios) visible to the
|
|
1309
|
+
caller. Capability-gated on `capabilities.agents.roster.supported:
|
|
1310
|
+
true`; hosts that don't advertise it return 404. Tenant-scoped per
|
|
1311
|
+
RFC 0074 — on an `installScope: 'tenant'` host only the caller's
|
|
1312
|
+
owner-triple entries are returned. Read-only; content-free (SR-1).
|
|
1313
|
+
operationId: listAgentRoster
|
|
1314
|
+
responses:
|
|
1315
|
+
'200':
|
|
1316
|
+
description: The caller's standing roster (rosterId-sorted).
|
|
1317
|
+
content:
|
|
1318
|
+
application/json:
|
|
1319
|
+
schema:
|
|
1320
|
+
$ref: '../schemas/agent-roster-response.schema.json'
|
|
1321
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1322
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1323
|
+
'404':
|
|
1324
|
+
description: Host does not advertise `capabilities.agents.roster`.
|
|
1325
|
+
content:
|
|
1326
|
+
application/json:
|
|
1327
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1328
|
+
|
|
1329
|
+
/v1/agents/roster/{rosterId}:
|
|
1330
|
+
get:
|
|
1331
|
+
tags: [agents]
|
|
1332
|
+
summary: |
|
|
1333
|
+
RFC 0086 §B — return one standing roster entry, or 404 when no such
|
|
1334
|
+
entry exists, the host doesn't advertise `capabilities.agents.roster`,
|
|
1335
|
+
or (on an `installScope: 'tenant'` host) the entry is outside the
|
|
1336
|
+
caller's owner triple — a cross-tenant entry 404s identically to
|
|
1337
|
+
"not found", never disclosing another tenant's roster.
|
|
1338
|
+
operationId: getAgentRosterEntry
|
|
1339
|
+
parameters:
|
|
1340
|
+
- in: path
|
|
1341
|
+
name: rosterId
|
|
1342
|
+
required: true
|
|
1343
|
+
schema: { type: string }
|
|
1344
|
+
description: The standing instance id (a `host:<id>` AgentRef agentId).
|
|
1345
|
+
responses:
|
|
1346
|
+
'200':
|
|
1347
|
+
description: The roster entry.
|
|
1348
|
+
content:
|
|
1349
|
+
application/json:
|
|
1350
|
+
schema:
|
|
1351
|
+
$ref: '../schemas/agent-roster-entry.schema.json'
|
|
1352
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1353
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1354
|
+
'404':
|
|
1355
|
+
description: No such entry, cross-tenant, or capability unadvertised.
|
|
1356
|
+
content:
|
|
1357
|
+
application/json:
|
|
1358
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1359
|
+
|
|
1360
|
+
/v1/agents/org-chart:
|
|
1361
|
+
get:
|
|
1362
|
+
tags: [agents]
|
|
1363
|
+
summary: |
|
|
1364
|
+
RFC 0087 §C — return the caller's agent org-chart (departments + roles
|
|
1365
|
+
+ `reportsTo` edges over roster members). Capability-gated on
|
|
1366
|
+
`capabilities.agents.orgChart.supported: true`; hosts that don't
|
|
1367
|
+
advertise it return 404. Tenant-scoped per RFC 0074. DESCRIPTIVE only:
|
|
1368
|
+
an org edge confers no authority (§B `org-position-no-authority-escalation`).
|
|
1369
|
+
operationId: getAgentOrgChart
|
|
1370
|
+
responses:
|
|
1371
|
+
'200':
|
|
1372
|
+
description: The caller's org-chart.
|
|
1373
|
+
content:
|
|
1374
|
+
application/json:
|
|
1375
|
+
schema:
|
|
1376
|
+
$ref: '../schemas/agent-org-chart.schema.json'
|
|
1377
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1378
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1379
|
+
'404':
|
|
1380
|
+
description: Host does not advertise `capabilities.agents.orgChart`.
|
|
1381
|
+
content:
|
|
1382
|
+
application/json:
|
|
1383
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1384
|
+
|
|
1385
|
+
/v1/agents/org-chart/{departmentId}:
|
|
1386
|
+
get:
|
|
1387
|
+
tags: [agents]
|
|
1388
|
+
summary: |
|
|
1389
|
+
RFC 0087 §D — one department's subtree + responsibility roll-up (the
|
|
1390
|
+
union of its members' RFC 0086 portfolios). `?recursive=false` narrows
|
|
1391
|
+
the roll-up to direct members without changing the response shape.
|
|
1392
|
+
404 when the department is unknown, cross-tenant, or the host doesn't
|
|
1393
|
+
advertise `capabilities.agents.orgChart`. The roll-up grants nothing (§B).
|
|
1394
|
+
operationId: getAgentOrgChartDepartment
|
|
1395
|
+
parameters:
|
|
1396
|
+
- in: path
|
|
1397
|
+
name: departmentId
|
|
1398
|
+
required: true
|
|
1399
|
+
schema: { type: string }
|
|
1400
|
+
description: The department id to root the subtree + roll-up at.
|
|
1401
|
+
- in: query
|
|
1402
|
+
name: recursive
|
|
1403
|
+
required: false
|
|
1404
|
+
schema: { type: boolean, default: true }
|
|
1405
|
+
description: When `false`, the roll-up scopes to direct members only.
|
|
1406
|
+
responses:
|
|
1407
|
+
'200':
|
|
1408
|
+
description: The department subtree + responsibility roll-up.
|
|
1409
|
+
content:
|
|
1410
|
+
application/json:
|
|
1411
|
+
schema:
|
|
1412
|
+
$ref: '../schemas/org-chart-responsibility-view.schema.json'
|
|
1413
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1414
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1415
|
+
'404':
|
|
1416
|
+
description: Unknown/cross-tenant department, or capability unadvertised.
|
|
1417
|
+
content:
|
|
1418
|
+
application/json:
|
|
1419
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1420
|
+
|
|
1421
|
+
/v1/tools:
|
|
1422
|
+
get:
|
|
1423
|
+
tags: [tools]
|
|
1424
|
+
summary: |
|
|
1425
|
+
RFC 0078 §B — list the portable `ToolDescriptor`s visible to the caller
|
|
1426
|
+
across every tool source (node-pack / workflow / mcp / connector /
|
|
1427
|
+
host-extension). Capability-gated on
|
|
1428
|
+
`capabilities.toolCatalog.supported: true`; hosts that don't advertise
|
|
1429
|
+
it return 404. §F-2 — the projection is authorization-scoped: a
|
|
1430
|
+
principal sees only the tools it may invoke, and a second principal MUST
|
|
1431
|
+
NOT see another principal's tools (non-disclosure). Read-only; each
|
|
1432
|
+
descriptor is content-free of any credential material (SR-1).
|
|
1433
|
+
operationId: listTools
|
|
1434
|
+
parameters:
|
|
1435
|
+
- name: view
|
|
1436
|
+
in: query
|
|
1437
|
+
required: false
|
|
1438
|
+
schema: { type: string, enum: [standard, compact], default: standard }
|
|
1439
|
+
description: >
|
|
1440
|
+
RFC 0112. `compact` returns the `{ tools: CompactToolDescriptor[] }`
|
|
1441
|
+
projection — heavy descriptor fields omitted and `inputSchema`
|
|
1442
|
+
bounded to the compact structural subset — when the host advertises
|
|
1443
|
+
`capabilities.toolCatalog.compactView: true`. Defaults to `standard`;
|
|
1444
|
+
a host that does not advertise `compactView` treats `view=compact`
|
|
1445
|
+
as any unknown query param and returns the standard view.
|
|
1446
|
+
responses:
|
|
1447
|
+
'200':
|
|
1448
|
+
description: 'The caller''s authorized tool catalog (standard array, or the compact `{ tools: [] }` projection when `view=compact`).'
|
|
1449
|
+
content:
|
|
1450
|
+
application/json:
|
|
1451
|
+
schema:
|
|
1452
|
+
oneOf:
|
|
1453
|
+
- type: array
|
|
1454
|
+
items: { $ref: '../schemas/tool-descriptor.schema.json' }
|
|
1455
|
+
- type: object
|
|
1456
|
+
required: [tools]
|
|
1457
|
+
properties:
|
|
1458
|
+
tools:
|
|
1459
|
+
type: array
|
|
1460
|
+
items: { $ref: '../schemas/compact-tool-descriptor.schema.json' }
|
|
1461
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1462
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1463
|
+
'404':
|
|
1464
|
+
description: Host does not advertise `capabilities.toolCatalog`.
|
|
1465
|
+
content:
|
|
1466
|
+
application/json:
|
|
1467
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1468
|
+
|
|
1469
|
+
/v1/tools/{toolId}:
|
|
1470
|
+
get:
|
|
1471
|
+
tags: [tools]
|
|
1472
|
+
summary: |
|
|
1473
|
+
RFC 0078 §B — return one `ToolDescriptor` by its stable `toolId`, or 404
|
|
1474
|
+
when no such tool exists, the caller isn't authorized for it (§F-2
|
|
1475
|
+
non-disclosure — a cross-principal tool 404s identically to "not
|
|
1476
|
+
found"), or the host doesn't advertise `capabilities.toolCatalog`.
|
|
1477
|
+
operationId: getTool
|
|
1478
|
+
parameters:
|
|
1479
|
+
- in: path
|
|
1480
|
+
name: toolId
|
|
1481
|
+
required: true
|
|
1482
|
+
schema: { type: string }
|
|
1483
|
+
description: The stable tool id (`ToolDescriptor.toolId`).
|
|
1484
|
+
- name: view
|
|
1485
|
+
in: query
|
|
1486
|
+
required: false
|
|
1487
|
+
schema: { type: string, enum: [standard, compact], default: standard }
|
|
1488
|
+
description: >
|
|
1489
|
+
RFC 0112. `compact` returns one `CompactToolDescriptor` (heavy
|
|
1490
|
+
fields omitted; `inputSchema` bounded to the compact structural
|
|
1491
|
+
subset) when the host advertises
|
|
1492
|
+
`capabilities.toolCatalog.compactView: true`. Defaults to
|
|
1493
|
+
`standard`; a host that does not advertise `compactView` treats
|
|
1494
|
+
`view=compact` as any unknown query param.
|
|
1495
|
+
responses:
|
|
1496
|
+
'200':
|
|
1497
|
+
description: The tool descriptor (standard, or one `CompactToolDescriptor` when `view=compact`).
|
|
1498
|
+
content:
|
|
1499
|
+
application/json:
|
|
1500
|
+
schema:
|
|
1501
|
+
oneOf:
|
|
1502
|
+
- $ref: '../schemas/tool-descriptor.schema.json'
|
|
1503
|
+
- $ref: '../schemas/compact-tool-descriptor.schema.json'
|
|
1504
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1505
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1506
|
+
'404':
|
|
1507
|
+
description: No such tool, unauthorized, or capability unadvertised.
|
|
1508
|
+
content:
|
|
1509
|
+
application/json:
|
|
1510
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1511
|
+
|
|
1512
|
+
/v1/runs/{runId}/eval-summary:
|
|
1513
|
+
get:
|
|
1514
|
+
tags: [runs]
|
|
1515
|
+
summary: |
|
|
1516
|
+
RFC 0081 §C — return the `EvalSummary` scorecard for a terminal eval run
|
|
1517
|
+
(a run started with `mode: "eval"`): aggregate + per-task scores, cost,
|
|
1518
|
+
latency, schema-validity, and redaction-safe safety findings, plus the
|
|
1519
|
+
suite provenance and (regression mode) the score delta vs a baseline.
|
|
1520
|
+
Content-free of task output / rubric prose / credentials (SR-1; the
|
|
1521
|
+
`eval-summary-no-content-leak` invariant). Capability-gated on
|
|
1522
|
+
`capabilities.agents.evalSuite.supported: true`; hosts that don't advertise
|
|
1523
|
+
it return 404. 409 when the run is not yet terminal.
|
|
1524
|
+
operationId: getEvalSummary
|
|
1525
|
+
parameters:
|
|
1526
|
+
- $ref: '#/components/parameters/RunId'
|
|
1527
|
+
responses:
|
|
1528
|
+
'200':
|
|
1529
|
+
description: The eval run's scorecard.
|
|
1530
|
+
content:
|
|
1531
|
+
application/json:
|
|
1532
|
+
schema:
|
|
1533
|
+
$ref: '../schemas/eval-summary.schema.json'
|
|
1534
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1535
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1536
|
+
'404':
|
|
1537
|
+
description: |
|
|
1538
|
+
No such run, the run is not an eval run, or the host doesn't advertise
|
|
1539
|
+
`capabilities.agents.evalSuite`.
|
|
1540
|
+
content:
|
|
1541
|
+
application/json:
|
|
1542
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1543
|
+
'409':
|
|
1544
|
+
description: The eval run is still running; the summary is not yet final.
|
|
1545
|
+
content:
|
|
1546
|
+
application/json:
|
|
1547
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1548
|
+
|
|
1549
|
+
/v1/runs/{runId}:diff:
|
|
1550
|
+
get:
|
|
1551
|
+
tags: [runs]
|
|
1552
|
+
summary: |
|
|
1553
|
+
RFC 0054 — return a deterministic, replay-aware structured diff of
|
|
1554
|
+
two runs (typically a run and its RFC 0011 fork): `divergedAtSeq` +
|
|
1555
|
+
ordered `eventDiffs[]` + `stateDiff`. The diff is a pure function of
|
|
1556
|
+
the two event logs (see `replay.md` determinism contract). Requires
|
|
1557
|
+
`runs:read` on BOTH runs. Hosts that don't implement it return 404.
|
|
1558
|
+
operationId: diffRun
|
|
1559
|
+
parameters:
|
|
1560
|
+
- $ref: '#/components/parameters/RunId'
|
|
1561
|
+
- name: against
|
|
1562
|
+
in: query
|
|
1563
|
+
required: true
|
|
1564
|
+
description: The other run id to diff `{runId}` against (the `b` run).
|
|
1565
|
+
schema: { type: string }
|
|
1566
|
+
responses:
|
|
1567
|
+
'200':
|
|
1568
|
+
description: |
|
|
1569
|
+
Structured diff of the two runs. `divergedAtSeq: null` + empty
|
|
1570
|
+
`eventDiffs` when the logs are identical.
|
|
1571
|
+
content:
|
|
1572
|
+
application/json:
|
|
1573
|
+
schema:
|
|
1574
|
+
$ref: '../schemas/run-diff-response.schema.json'
|
|
1575
|
+
'400':
|
|
1576
|
+
description: Missing or malformed `against` query parameter.
|
|
1577
|
+
content:
|
|
1578
|
+
application/json:
|
|
1579
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1580
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1581
|
+
'403':
|
|
1582
|
+
description: |
|
|
1583
|
+
Caller lacks `runs:read` on `{runId}` and/or on `against`
|
|
1584
|
+
(`forbidden`); composes with RFC 0048 cross-workspace
|
|
1585
|
+
isolation.
|
|
1586
|
+
content:
|
|
1587
|
+
application/json:
|
|
1588
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1589
|
+
'404':
|
|
1590
|
+
description: |
|
|
1591
|
+
Either run doesn't exist, OR the host doesn't implement the diff
|
|
1592
|
+
endpoint and treats the path as absent.
|
|
1593
|
+
content:
|
|
1594
|
+
application/json:
|
|
1595
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1596
|
+
|
|
1597
|
+
/v1/runs/{runId}:pause:
|
|
1598
|
+
post:
|
|
1599
|
+
tags: [runs]
|
|
1600
|
+
summary: Administratively pause an in-flight run (RFC Track 13).
|
|
1601
|
+
description: |
|
|
1602
|
+
Operator-driven pause distinct from cancel (terminal) and HITL suspend (workflow-driven).
|
|
1603
|
+
Emits a `run.paused` event when the pause takes effect; exit only via `:resume` or `:cancel`.
|
|
1604
|
+
operationId: pauseRun
|
|
1605
|
+
parameters:
|
|
1606
|
+
- $ref: '#/components/parameters/RunId'
|
|
1607
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1608
|
+
requestBody:
|
|
1609
|
+
content:
|
|
1610
|
+
application/json:
|
|
1611
|
+
schema:
|
|
1612
|
+
type: object
|
|
1613
|
+
properties:
|
|
1614
|
+
reason:
|
|
1615
|
+
type: string
|
|
1616
|
+
description: Free-form rationale, persisted on the `run.paused` event payload.
|
|
1617
|
+
drainPolicy:
|
|
1618
|
+
type: string
|
|
1619
|
+
enum: [immediate, drain-current-node]
|
|
1620
|
+
default: drain-current-node
|
|
1621
|
+
description: |
|
|
1622
|
+
`immediate` snapshots between events; `drain-current-node` lets the running node
|
|
1623
|
+
reach a terminal before transitioning to `paused`.
|
|
1624
|
+
additionalProperties: false
|
|
1625
|
+
responses:
|
|
1626
|
+
'202':
|
|
1627
|
+
description: Pause requested; transition emits `run.paused` when complete.
|
|
1628
|
+
content:
|
|
1629
|
+
application/json:
|
|
1630
|
+
schema:
|
|
1631
|
+
type: object
|
|
1632
|
+
required: [runId, status]
|
|
1633
|
+
properties:
|
|
1634
|
+
runId: { type: string }
|
|
1635
|
+
status: { type: string, enum: [paused] }
|
|
1636
|
+
pausedAt: { type: string, format: date-time }
|
|
1637
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1638
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1639
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
1640
|
+
'409':
|
|
1641
|
+
description: Run is already paused, terminal, or in a state that cannot be paused.
|
|
1642
|
+
content:
|
|
1643
|
+
application/json:
|
|
1644
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1645
|
+
|
|
1646
|
+
/v1/runs/{runId}:resume:
|
|
1647
|
+
post:
|
|
1648
|
+
tags: [runs]
|
|
1649
|
+
summary: Resume a paused run (RFC Track 13).
|
|
1650
|
+
description: |
|
|
1651
|
+
Reverses a prior `:pause`. Run transitions from `paused` to `running` and emits `run.resumed`.
|
|
1652
|
+
operationId: resumeRun
|
|
1653
|
+
parameters:
|
|
1654
|
+
- $ref: '#/components/parameters/RunId'
|
|
1655
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1656
|
+
requestBody:
|
|
1657
|
+
content:
|
|
1658
|
+
application/json:
|
|
1659
|
+
schema:
|
|
1660
|
+
type: object
|
|
1661
|
+
properties:
|
|
1662
|
+
reason: { type: string }
|
|
1663
|
+
additionalProperties: false
|
|
1664
|
+
responses:
|
|
1665
|
+
'202':
|
|
1666
|
+
description: Resume requested.
|
|
1667
|
+
content:
|
|
1668
|
+
application/json:
|
|
1669
|
+
schema:
|
|
1670
|
+
type: object
|
|
1671
|
+
required: [runId, status]
|
|
1672
|
+
properties:
|
|
1673
|
+
runId: { type: string }
|
|
1674
|
+
status: { type: string, enum: [running] }
|
|
1675
|
+
resumedAt: { type: string, format: date-time }
|
|
1676
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1677
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1678
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
1679
|
+
'409':
|
|
1680
|
+
description: Run is not currently paused.
|
|
1681
|
+
content:
|
|
1682
|
+
application/json:
|
|
1683
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1684
|
+
|
|
1685
|
+
# ── HITL ────────────────────────────────────────────────────────────────
|
|
1686
|
+
/v1/runs/{runId}/interrupts/{nodeId}:
|
|
1687
|
+
post:
|
|
1688
|
+
tags: [hitl]
|
|
1689
|
+
summary: Resolve an interrupt via the run-scoped surface.
|
|
1690
|
+
operationId: resolveInterruptByRun
|
|
1691
|
+
parameters:
|
|
1692
|
+
- $ref: '#/components/parameters/RunId'
|
|
1693
|
+
- in: path
|
|
1694
|
+
name: nodeId
|
|
1695
|
+
required: true
|
|
1696
|
+
schema: { type: string, minLength: 1 }
|
|
1697
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1698
|
+
requestBody:
|
|
1699
|
+
required: true
|
|
1700
|
+
content:
|
|
1701
|
+
application/json:
|
|
1702
|
+
schema:
|
|
1703
|
+
type: object
|
|
1704
|
+
required: [resumeValue]
|
|
1705
|
+
properties:
|
|
1706
|
+
resumeValue:
|
|
1707
|
+
description: Validated against the interrupt's `resumeSchema` if declared.
|
|
1708
|
+
additionalProperties: false
|
|
1709
|
+
responses:
|
|
1710
|
+
'200':
|
|
1711
|
+
description: Interrupt resolved; executor unblocks.
|
|
1712
|
+
content:
|
|
1713
|
+
application/json:
|
|
1714
|
+
schema:
|
|
1715
|
+
type: object
|
|
1716
|
+
properties:
|
|
1717
|
+
runId: { type: string }
|
|
1718
|
+
nodeId: { type: string }
|
|
1719
|
+
status: { type: string }
|
|
1720
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
1721
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1722
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1723
|
+
'404':
|
|
1724
|
+
description: Interrupt not found or already resolved.
|
|
1725
|
+
content:
|
|
1726
|
+
application/json:
|
|
1727
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1728
|
+
'409':
|
|
1729
|
+
description: Concurrent resolve — only one wins.
|
|
1730
|
+
content:
|
|
1731
|
+
application/json:
|
|
1732
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1733
|
+
'422':
|
|
1734
|
+
description: Run was cancelled while interrupt was pending.
|
|
1735
|
+
content:
|
|
1736
|
+
application/json:
|
|
1737
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1738
|
+
|
|
1739
|
+
/v1/interrupts/{token}:
|
|
1740
|
+
parameters:
|
|
1741
|
+
- in: path
|
|
1742
|
+
name: token
|
|
1743
|
+
required: true
|
|
1744
|
+
schema: { type: string }
|
|
1745
|
+
description: HMAC-signed token issued by the server at suspension time. Format `base64url(payload).hmac_sha256(secret, payload)`.
|
|
1746
|
+
get:
|
|
1747
|
+
tags: [hitl]
|
|
1748
|
+
summary: Inspect an interrupt without resolving (signed-token surface).
|
|
1749
|
+
operationId: inspectInterruptByToken
|
|
1750
|
+
security: [] # token is the auth
|
|
1751
|
+
responses:
|
|
1752
|
+
'200':
|
|
1753
|
+
description: Interrupt details.
|
|
1754
|
+
content:
|
|
1755
|
+
application/json:
|
|
1756
|
+
schema: { $ref: '../schemas/suspend-request.schema.json' }
|
|
1757
|
+
'410':
|
|
1758
|
+
description: Token expired.
|
|
1759
|
+
content:
|
|
1760
|
+
application/json:
|
|
1761
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1762
|
+
post:
|
|
1763
|
+
tags: [hitl]
|
|
1764
|
+
summary: Resolve an interrupt via signed token (asynchronous callback).
|
|
1765
|
+
operationId: resolveInterruptByToken
|
|
1766
|
+
security: [] # token is the auth
|
|
1767
|
+
parameters:
|
|
1768
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1769
|
+
requestBody:
|
|
1770
|
+
required: true
|
|
1771
|
+
content:
|
|
1772
|
+
application/json:
|
|
1773
|
+
schema:
|
|
1774
|
+
type: object
|
|
1775
|
+
required: [resumeValue]
|
|
1776
|
+
properties:
|
|
1777
|
+
resumeValue: {}
|
|
1778
|
+
additionalProperties: false
|
|
1779
|
+
responses:
|
|
1780
|
+
'200':
|
|
1781
|
+
description: Resolution accepted.
|
|
1782
|
+
content:
|
|
1783
|
+
application/json:
|
|
1784
|
+
schema: { type: object }
|
|
1785
|
+
'410':
|
|
1786
|
+
description: Token expired.
|
|
1787
|
+
content:
|
|
1788
|
+
application/json:
|
|
1789
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
1790
|
+
|
|
1791
|
+
# ── Artifacts ───────────────────────────────────────────────────────────
|
|
1792
|
+
/v1/runs/{runId}/artifacts/{artifactId}:
|
|
1793
|
+
get:
|
|
1794
|
+
tags: [artifacts]
|
|
1795
|
+
summary: Read a run-produced artifact.
|
|
1796
|
+
operationId: getArtifact
|
|
1797
|
+
parameters:
|
|
1798
|
+
- $ref: '#/components/parameters/RunId'
|
|
1799
|
+
- in: path
|
|
1800
|
+
name: artifactId
|
|
1801
|
+
required: true
|
|
1802
|
+
schema: { type: string, minLength: 1 }
|
|
1803
|
+
responses:
|
|
1804
|
+
'200':
|
|
1805
|
+
description: Artifact payload.
|
|
1806
|
+
content:
|
|
1807
|
+
application/json:
|
|
1808
|
+
schema:
|
|
1809
|
+
type: object
|
|
1810
|
+
description: Implementation-defined artifact shape.
|
|
1811
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1812
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1813
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
1814
|
+
|
|
1815
|
+
# ── Webhooks ────────────────────────────────────────────────────────────
|
|
1816
|
+
/v1/webhooks:
|
|
1817
|
+
post:
|
|
1818
|
+
tags: [webhooks]
|
|
1819
|
+
summary: Register a webhook subscription.
|
|
1820
|
+
operationId: registerWebhook
|
|
1821
|
+
parameters:
|
|
1822
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1823
|
+
requestBody:
|
|
1824
|
+
required: true
|
|
1825
|
+
content:
|
|
1826
|
+
application/json:
|
|
1827
|
+
schema:
|
|
1828
|
+
type: object
|
|
1829
|
+
required: [url, events]
|
|
1830
|
+
properties:
|
|
1831
|
+
url: { type: string, format: uri }
|
|
1832
|
+
events:
|
|
1833
|
+
type: array
|
|
1834
|
+
items: { type: string }
|
|
1835
|
+
description: Event types to subscribe to (see `run-event.schema.json` enum).
|
|
1836
|
+
secret:
|
|
1837
|
+
type: string
|
|
1838
|
+
description: Server signs payloads with this secret using HMAC-SHA256.
|
|
1839
|
+
tags:
|
|
1840
|
+
type: array
|
|
1841
|
+
items: { type: string }
|
|
1842
|
+
description: Filter to runs carrying these tags (see `run-options.md`).
|
|
1843
|
+
additionalProperties: false
|
|
1844
|
+
responses:
|
|
1845
|
+
'201':
|
|
1846
|
+
description: Webhook registered.
|
|
1847
|
+
content:
|
|
1848
|
+
application/json:
|
|
1849
|
+
schema:
|
|
1850
|
+
type: object
|
|
1851
|
+
required: [webhookId]
|
|
1852
|
+
properties:
|
|
1853
|
+
webhookId: { type: string }
|
|
1854
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
1855
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1856
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1857
|
+
|
|
1858
|
+
/v1/webhooks/{webhookId}:
|
|
1859
|
+
delete:
|
|
1860
|
+
tags: [webhooks]
|
|
1861
|
+
summary: Unregister a webhook.
|
|
1862
|
+
operationId: unregisterWebhook
|
|
1863
|
+
parameters:
|
|
1864
|
+
- in: path
|
|
1865
|
+
name: webhookId
|
|
1866
|
+
required: true
|
|
1867
|
+
schema: { type: string, minLength: 1 }
|
|
1868
|
+
responses:
|
|
1869
|
+
'204':
|
|
1870
|
+
description: Unregistered.
|
|
1871
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1872
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1873
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
1874
|
+
|
|
1875
|
+
# ── Audit-log integrity verification (gated on profile) ────────────────
|
|
1876
|
+
/v1/audit/verify:
|
|
1877
|
+
get:
|
|
1878
|
+
tags: [audit]
|
|
1879
|
+
summary: Verify the audit-log hash chain over [fromSeq, toSeq].
|
|
1880
|
+
description: |
|
|
1881
|
+
Per `spec/v1/auth-profiles.md` §`openwop-audit-log-integrity` §4. The
|
|
1882
|
+
verifier re-walks audit-log entries in the requested range,
|
|
1883
|
+
re-computes each entry's `prevHash` from the canonical RFC 8785 JCS
|
|
1884
|
+
serialization of the prior entry, verifies signed checkpoints
|
|
1885
|
+
against the host's advertised `auditLogIntegrity.checkpointPublicKey`,
|
|
1886
|
+
and returns `chainValid` + an enumeration of any anomalies.
|
|
1887
|
+
Hosts MUST require the `audit:read` scope. Hosts that do NOT
|
|
1888
|
+
advertise the `openwop-audit-log-integrity` profile MAY omit this
|
|
1889
|
+
endpoint entirely (clients SHOULD pre-flight via `/.well-known/openwop`).
|
|
1890
|
+
operationId: verifyAuditLog
|
|
1891
|
+
parameters:
|
|
1892
|
+
- in: query
|
|
1893
|
+
name: fromSeq
|
|
1894
|
+
required: true
|
|
1895
|
+
schema: { type: integer, minimum: 0 }
|
|
1896
|
+
description: First audit-log sequence to include (inclusive).
|
|
1897
|
+
- in: query
|
|
1898
|
+
name: toSeq
|
|
1899
|
+
required: true
|
|
1900
|
+
schema: { type: integer, minimum: 0 }
|
|
1901
|
+
description: Last audit-log sequence to include (inclusive). MUST be >= fromSeq.
|
|
1902
|
+
responses:
|
|
1903
|
+
'200':
|
|
1904
|
+
description: Verification result.
|
|
1905
|
+
content:
|
|
1906
|
+
application/json:
|
|
1907
|
+
schema:
|
|
1908
|
+
$ref: '../schemas/audit-verify-result.schema.json'
|
|
1909
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
1910
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1911
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1912
|
+
'404':
|
|
1913
|
+
description: Host does not advertise the audit-log-integrity profile.
|
|
1914
|
+
content:
|
|
1915
|
+
application/json:
|
|
1916
|
+
schema:
|
|
1917
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
1918
|
+
|
|
1919
|
+
# ── Prompt library (RFC 0028) ────────────────────────────────────────
|
|
1920
|
+
# Surface gated on `capabilities.prompts.supported: true`. Mutating
|
|
1921
|
+
# endpoints (POST / PUT / DELETE) are additionally gated on
|
|
1922
|
+
# `capabilities.prompts.mutableLibrary: true`. Hosts without the
|
|
1923
|
+
# advertised capability return `501 capability_not_provided`.
|
|
1924
|
+
/v1/prompts:
|
|
1925
|
+
get:
|
|
1926
|
+
tags: [prompts]
|
|
1927
|
+
summary: List prompt templates available to the caller.
|
|
1928
|
+
operationId: listPromptTemplates
|
|
1929
|
+
parameters:
|
|
1930
|
+
- in: query
|
|
1931
|
+
name: kind
|
|
1932
|
+
schema: { type: string, enum: [system, user, few-shot, schema-hint] }
|
|
1933
|
+
description: Filter by `PromptTemplate.kind`.
|
|
1934
|
+
- in: query
|
|
1935
|
+
name: tag
|
|
1936
|
+
schema: { type: string }
|
|
1937
|
+
description: |
|
|
1938
|
+
Filter to templates whose `tags[]` contains this exact tag.
|
|
1939
|
+
Hosts MAY accept the parameter multiple times; the semantic
|
|
1940
|
+
when repeated is AND (every named tag must be present).
|
|
1941
|
+
- in: query
|
|
1942
|
+
name: modelClass
|
|
1943
|
+
schema: { type: string }
|
|
1944
|
+
description: Filter to templates whose `modelHints.modelClass` matches.
|
|
1945
|
+
- in: query
|
|
1946
|
+
name: source
|
|
1947
|
+
schema: { type: string, enum: [host, pack, user] }
|
|
1948
|
+
description: Filter by `meta.source` provenance.
|
|
1949
|
+
- in: query
|
|
1950
|
+
name: cursor
|
|
1951
|
+
schema: { type: string }
|
|
1952
|
+
description: Opaque pagination cursor.
|
|
1953
|
+
- in: query
|
|
1954
|
+
name: limit
|
|
1955
|
+
schema: { type: integer, minimum: 1, maximum: 200, default: 50 }
|
|
1956
|
+
description: Maximum entries per page.
|
|
1957
|
+
responses:
|
|
1958
|
+
'200':
|
|
1959
|
+
description: Paginated list of templates.
|
|
1960
|
+
content:
|
|
1961
|
+
application/json:
|
|
1962
|
+
schema:
|
|
1963
|
+
type: object
|
|
1964
|
+
required: [items]
|
|
1965
|
+
properties:
|
|
1966
|
+
items:
|
|
1967
|
+
type: array
|
|
1968
|
+
items:
|
|
1969
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
1970
|
+
nextCursor:
|
|
1971
|
+
type: string
|
|
1972
|
+
description: Opaque cursor; absent on the final page.
|
|
1973
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
1974
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
1975
|
+
'501':
|
|
1976
|
+
description: 'Host does not advertise capabilities.prompts.endpointsSupported. (RFC 0028 §A — supported gates Phase A node-execution composition; endpointsSupported gates this REST surface independently.)'
|
|
1977
|
+
content:
|
|
1978
|
+
application/json:
|
|
1979
|
+
schema:
|
|
1980
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
1981
|
+
post:
|
|
1982
|
+
tags: [prompts]
|
|
1983
|
+
summary: Create a new prompt template (mutable libraries only).
|
|
1984
|
+
operationId: createPromptTemplate
|
|
1985
|
+
parameters:
|
|
1986
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
1987
|
+
requestBody:
|
|
1988
|
+
required: true
|
|
1989
|
+
content:
|
|
1990
|
+
application/json:
|
|
1991
|
+
schema:
|
|
1992
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
1993
|
+
responses:
|
|
1994
|
+
'201':
|
|
1995
|
+
description: Template created. `Location` header carries the canonical URI.
|
|
1996
|
+
headers:
|
|
1997
|
+
Location:
|
|
1998
|
+
schema: { type: string }
|
|
1999
|
+
description: 'Canonical URI of the new template.'
|
|
2000
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
2001
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2002
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
2003
|
+
'409':
|
|
2004
|
+
description: A template with this `(templateId, version)` pair already exists.
|
|
2005
|
+
content:
|
|
2006
|
+
application/json:
|
|
2007
|
+
schema:
|
|
2008
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2009
|
+
'501':
|
|
2010
|
+
description: 'Host does not advertise capabilities.prompts.mutableLibrary.'
|
|
2011
|
+
content:
|
|
2012
|
+
application/json:
|
|
2013
|
+
schema:
|
|
2014
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2015
|
+
|
|
2016
|
+
/v1/prompts/{templateId}:
|
|
2017
|
+
parameters:
|
|
2018
|
+
- in: path
|
|
2019
|
+
name: templateId
|
|
2020
|
+
required: true
|
|
2021
|
+
schema:
|
|
2022
|
+
type: string
|
|
2023
|
+
pattern: '^[a-z0-9][a-z0-9._-]{0,127}$'
|
|
2024
|
+
description: PromptTemplate.templateId per RFC 0027.
|
|
2025
|
+
- in: query
|
|
2026
|
+
name: version
|
|
2027
|
+
schema:
|
|
2028
|
+
type: string
|
|
2029
|
+
pattern: '^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$'
|
|
2030
|
+
description: Pin to a specific SemVer version; latest when omitted.
|
|
2031
|
+
- in: query
|
|
2032
|
+
name: libraryId
|
|
2033
|
+
schema:
|
|
2034
|
+
type: string
|
|
2035
|
+
pattern: '^[a-z0-9][a-z0-9._-]{0,127}$'
|
|
2036
|
+
description: |
|
|
2037
|
+
Disambiguate when multiple installed packs ship the same
|
|
2038
|
+
templateId. Hosts MUST return `prompt_ref_ambiguous` if
|
|
2039
|
+
ambiguous and libraryId is omitted.
|
|
2040
|
+
get:
|
|
2041
|
+
tags: [prompts]
|
|
2042
|
+
summary: Fetch a single prompt template.
|
|
2043
|
+
operationId: getPromptTemplate
|
|
2044
|
+
responses:
|
|
2045
|
+
'200':
|
|
2046
|
+
description: The PromptTemplate.
|
|
2047
|
+
headers:
|
|
2048
|
+
ETag:
|
|
2049
|
+
schema: { type: string }
|
|
2050
|
+
description: SHA-256 of the canonical body.
|
|
2051
|
+
Cache-Control:
|
|
2052
|
+
schema: { type: string }
|
|
2053
|
+
description: Honors immutable semantics when version was pinned.
|
|
2054
|
+
content:
|
|
2055
|
+
application/json:
|
|
2056
|
+
schema:
|
|
2057
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
2058
|
+
'304':
|
|
2059
|
+
description: Conditional revalidation succeeded.
|
|
2060
|
+
'400':
|
|
2061
|
+
description: '`prompt_ref_ambiguous` when libraryId disambiguation is required.'
|
|
2062
|
+
content:
|
|
2063
|
+
application/json:
|
|
2064
|
+
schema:
|
|
2065
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2066
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2067
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
2068
|
+
'404':
|
|
2069
|
+
description: No such template (or version).
|
|
2070
|
+
content:
|
|
2071
|
+
application/json:
|
|
2072
|
+
schema:
|
|
2073
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2074
|
+
'501':
|
|
2075
|
+
description: 'Host does not advertise capabilities.prompts.endpointsSupported. (RFC 0028 §A — supported gates Phase A node-execution composition; endpointsSupported gates this REST surface independently.)'
|
|
2076
|
+
content:
|
|
2077
|
+
application/json:
|
|
2078
|
+
schema:
|
|
2079
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2080
|
+
put:
|
|
2081
|
+
tags: [prompts]
|
|
2082
|
+
summary: Replace a prompt template (mutable libraries; user-source only).
|
|
2083
|
+
operationId: updatePromptTemplate
|
|
2084
|
+
parameters:
|
|
2085
|
+
- $ref: '#/components/parameters/IdempotencyKey'
|
|
2086
|
+
requestBody:
|
|
2087
|
+
required: true
|
|
2088
|
+
content:
|
|
2089
|
+
application/json:
|
|
2090
|
+
schema:
|
|
2091
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
2092
|
+
responses:
|
|
2093
|
+
'200':
|
|
2094
|
+
description: Template updated.
|
|
2095
|
+
content:
|
|
2096
|
+
application/json:
|
|
2097
|
+
schema:
|
|
2098
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
2099
|
+
'400': { $ref: '#/components/responses/ValidationError' }
|
|
2100
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2101
|
+
'403':
|
|
2102
|
+
description: Template is pack-sourced or host-built-in (read-only).
|
|
2103
|
+
content:
|
|
2104
|
+
application/json:
|
|
2105
|
+
schema:
|
|
2106
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2107
|
+
'404':
|
|
2108
|
+
description: No such template.
|
|
2109
|
+
content:
|
|
2110
|
+
application/json:
|
|
2111
|
+
schema:
|
|
2112
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2113
|
+
'409':
|
|
2114
|
+
description: Submitted version does not exceed stored version (SemVer).
|
|
2115
|
+
content:
|
|
2116
|
+
application/json:
|
|
2117
|
+
schema:
|
|
2118
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2119
|
+
'501':
|
|
2120
|
+
description: 'Host does not advertise capabilities.prompts.mutableLibrary.'
|
|
2121
|
+
content:
|
|
2122
|
+
application/json:
|
|
2123
|
+
schema:
|
|
2124
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2125
|
+
delete:
|
|
2126
|
+
tags: [prompts]
|
|
2127
|
+
summary: Delete a prompt template (mutable libraries; user-source only).
|
|
2128
|
+
operationId: deletePromptTemplate
|
|
2129
|
+
responses:
|
|
2130
|
+
'204':
|
|
2131
|
+
description: Template deleted.
|
|
2132
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2133
|
+
'403':
|
|
2134
|
+
description: Template is pack-sourced or host-built-in (read-only).
|
|
2135
|
+
content:
|
|
2136
|
+
application/json:
|
|
2137
|
+
schema:
|
|
2138
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2139
|
+
'404':
|
|
2140
|
+
description: No such template.
|
|
2141
|
+
content:
|
|
2142
|
+
application/json:
|
|
2143
|
+
schema:
|
|
2144
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2145
|
+
'501':
|
|
2146
|
+
description: 'Host does not advertise capabilities.prompts.mutableLibrary.'
|
|
2147
|
+
content:
|
|
2148
|
+
application/json:
|
|
2149
|
+
schema:
|
|
2150
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2151
|
+
|
|
2152
|
+
/v1/prompts:render:
|
|
2153
|
+
post:
|
|
2154
|
+
tags: [prompts]
|
|
2155
|
+
summary: Render a prompt template with supplied variable bindings.
|
|
2156
|
+
description: |
|
|
2157
|
+
Returns the composed body + sha256 hash + per-variable hashes.
|
|
2158
|
+
The response's `hash` MUST equal the `hash` that a matching
|
|
2159
|
+
`prompt.composed` event would carry at dispatch time for the
|
|
2160
|
+
same `(ref, variables, contentTrust)` inputs (RFC 0028 §A
|
|
2161
|
+
deterministic-render invariant; RFC 0027 §F replay invariant).
|
|
2162
|
+
Does NOT dispatch an LLM call. Secret-source variable values
|
|
2163
|
+
MUST be supplied as `[REDACTED:<credentialRef>]` markers; the
|
|
2164
|
+
host resolves the plaintext internally and never echoes it in
|
|
2165
|
+
the `composed` response field per SR-1.
|
|
2166
|
+
operationId: renderPromptTemplate
|
|
2167
|
+
requestBody:
|
|
2168
|
+
required: true
|
|
2169
|
+
content:
|
|
2170
|
+
application/json:
|
|
2171
|
+
schema:
|
|
2172
|
+
type: object
|
|
2173
|
+
required: [ref, variables]
|
|
2174
|
+
properties:
|
|
2175
|
+
ref:
|
|
2176
|
+
$ref: '../schemas/prompt-ref.schema.json'
|
|
2177
|
+
variables:
|
|
2178
|
+
type: object
|
|
2179
|
+
description: |
|
|
2180
|
+
Variable bindings keyed by `PromptVariable.name`.
|
|
2181
|
+
Secret-source bindings carry `[REDACTED:<credentialRef>]`
|
|
2182
|
+
markers; the host resolves the real value internally.
|
|
2183
|
+
additionalProperties: true
|
|
2184
|
+
contentTrust:
|
|
2185
|
+
type: string
|
|
2186
|
+
enum: [trusted, untrusted]
|
|
2187
|
+
description: |
|
|
2188
|
+
Aggregate trust marker for the supplied bindings,
|
|
2189
|
+
propagated through composition per RFC 0027 §E.
|
|
2190
|
+
responses:
|
|
2191
|
+
'200':
|
|
2192
|
+
description: Composed result.
|
|
2193
|
+
content:
|
|
2194
|
+
application/json:
|
|
2195
|
+
schema:
|
|
2196
|
+
type: object
|
|
2197
|
+
required: [hash, refs, variableHashes]
|
|
2198
|
+
properties:
|
|
2199
|
+
composed:
|
|
2200
|
+
type: string
|
|
2201
|
+
description: Full composed body. Present only when observability is `full`.
|
|
2202
|
+
hash:
|
|
2203
|
+
type: string
|
|
2204
|
+
pattern: '^sha256:[0-9a-f]{64}$'
|
|
2205
|
+
refs:
|
|
2206
|
+
type: array
|
|
2207
|
+
items:
|
|
2208
|
+
type: string
|
|
2209
|
+
variableHashes:
|
|
2210
|
+
type: object
|
|
2211
|
+
additionalProperties:
|
|
2212
|
+
type: string
|
|
2213
|
+
pattern: '^sha256:[0-9a-f]{64}$'
|
|
2214
|
+
contentTrust:
|
|
2215
|
+
type: string
|
|
2216
|
+
enum: [trusted, untrusted]
|
|
2217
|
+
'400':
|
|
2218
|
+
description: |
|
|
2219
|
+
`prompt_variable_unresolved` (required variable missing),
|
|
2220
|
+
`prompt_variable_type_mismatch` (bound type vs. declared type),
|
|
2221
|
+
or `prompt_ref_invalid` (malformed PromptRef).
|
|
2222
|
+
content:
|
|
2223
|
+
application/json:
|
|
2224
|
+
schema:
|
|
2225
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2226
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2227
|
+
'403': { $ref: '#/components/responses/Forbidden' }
|
|
2228
|
+
'404':
|
|
2229
|
+
description: Referenced template does not exist.
|
|
2230
|
+
content:
|
|
2231
|
+
application/json:
|
|
2232
|
+
schema:
|
|
2233
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2234
|
+
'501':
|
|
2235
|
+
description: 'Host does not advertise capabilities.prompts.endpointsSupported. (RFC 0028 §A — supported gates Phase A node-execution composition; endpointsSupported gates this REST surface independently.)'
|
|
2236
|
+
content:
|
|
2237
|
+
application/json:
|
|
2238
|
+
schema:
|
|
2239
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2240
|
+
|
|
2241
|
+
# ── Test-mode pack registry namespace (RFC 0025) ─────────────────────────
|
|
2242
|
+
# Mirrors the production /v1/packs/* PUT/GET/DELETE/.sig surface against an
|
|
2243
|
+
# isolated catalog. Conformance scenarios under
|
|
2244
|
+
# `conformance/src/scenarios/pack-registry-publish.test.ts` exercise the
|
|
2245
|
+
# 19-code publish error catalog through this namespace. Hosts that don't
|
|
2246
|
+
# advertise `capabilities.packs.testMode.supported: true` MUST return
|
|
2247
|
+
# 404 for every path below.
|
|
2248
|
+
|
|
2249
|
+
/v1/packs-test/{name}/-/{version}.tgz:
|
|
2250
|
+
parameters:
|
|
2251
|
+
- $ref: '#/components/parameters/PackName'
|
|
2252
|
+
- $ref: '#/components/parameters/PackVersion'
|
|
2253
|
+
put:
|
|
2254
|
+
tags: [packs-test]
|
|
2255
|
+
summary: Publish a pack tarball to the isolated test catalog.
|
|
2256
|
+
description: |
|
|
2257
|
+
Mirror of `PUT /v1/packs/{name}/-/{version}.tgz` per
|
|
2258
|
+
`spec/v1/node-packs.md` §"PUT /v1/packs/{name}/-/{version}.tgz".
|
|
2259
|
+
Request shape, response shape, status codes, and the 19-code
|
|
2260
|
+
publish error catalog (`invalid_pack_scope`, `invalid_pack_name`,
|
|
2261
|
+
`invalid_version`, `invalid_body`, eight `tarball_*` codes,
|
|
2262
|
+
`invalid_manifest`, `manifest_mismatch` (or the granular
|
|
2263
|
+
`manifest_name_mismatch` / `manifest_version_mismatch` pair),
|
|
2264
|
+
`pack_integrity_failure`, `unsupported_runtime`, `forbidden`,
|
|
2265
|
+
`conflict`/`version_conflict`) MUST be served verbatim. The
|
|
2266
|
+
test catalog MUST be isolated per RFC 0025 §C — a pack PUT'd
|
|
2267
|
+
here MUST NOT appear in `GET /v1/packs/{name}` listings.
|
|
2268
|
+
The mirrored production path is registry-service surface
|
|
2269
|
+
(`registry-operations.md`), not defined in this host document
|
|
2270
|
+
(see the `packs-test` tag scope note).
|
|
2271
|
+
operationId: putTestPackTarball
|
|
2272
|
+
parameters:
|
|
2273
|
+
- in: header
|
|
2274
|
+
name: X-Pack-Signing-Method
|
|
2275
|
+
required: false
|
|
2276
|
+
schema: { type: string, enum: [sigstore, manual, none] }
|
|
2277
|
+
- in: header
|
|
2278
|
+
name: X-Pack-Sha256
|
|
2279
|
+
required: false
|
|
2280
|
+
schema:
|
|
2281
|
+
type: string
|
|
2282
|
+
pattern: '^sha256-[A-Za-z0-9+/=]+$'
|
|
2283
|
+
description: Caller-asserted SHA-256 (server verifies; mismatch surfaces `pack_integrity_failure`).
|
|
2284
|
+
requestBody:
|
|
2285
|
+
required: true
|
|
2286
|
+
description: Gzipped tarball bytes (`application/tar+gzip`, `application/gzip`, `application/x-gzip`, or `application/octet-stream`).
|
|
2287
|
+
content:
|
|
2288
|
+
application/gzip:
|
|
2289
|
+
schema: { type: string, format: binary }
|
|
2290
|
+
application/x-gzip:
|
|
2291
|
+
schema: { type: string, format: binary }
|
|
2292
|
+
application/tar+gzip:
|
|
2293
|
+
schema: { type: string, format: binary }
|
|
2294
|
+
application/octet-stream:
|
|
2295
|
+
schema: { type: string, format: binary }
|
|
2296
|
+
responses:
|
|
2297
|
+
'200':
|
|
2298
|
+
description: Idempotent re-publish — identical sha256 content already published; existing record returned.
|
|
2299
|
+
content:
|
|
2300
|
+
application/json:
|
|
2301
|
+
schema: { $ref: '#/components/schemas/TestPackPublishRecord' }
|
|
2302
|
+
'201':
|
|
2303
|
+
description: New version published to the test catalog.
|
|
2304
|
+
content:
|
|
2305
|
+
application/json:
|
|
2306
|
+
schema: { $ref: '#/components/schemas/TestPackPublishRecord' }
|
|
2307
|
+
'400':
|
|
2308
|
+
description: |
|
|
2309
|
+
One of the 17 spec-documented 400-class publish error codes:
|
|
2310
|
+
URL/scope (`invalid_pack_scope`, `invalid_pack_name`, `invalid_version`),
|
|
2311
|
+
body shape (`invalid_body`),
|
|
2312
|
+
tarball extraction (`tarball_gunzip_failed`, `tarball_too_large`,
|
|
2313
|
+
`tarball_manifest_missing`, `tarball_manifest_too_large`,
|
|
2314
|
+
`tarball_manifest_not_json`, `tarball_entry_missing`,
|
|
2315
|
+
`tarball_entry_too_large`, `tarball_path_traversal`,
|
|
2316
|
+
`tarball_tar_parse_failed`),
|
|
2317
|
+
manifest contents (`invalid_manifest`, `manifest_mismatch` or
|
|
2318
|
+
the granular `manifest_name_mismatch` / `manifest_version_mismatch` pair,
|
|
2319
|
+
`pack_integrity_failure`, `unsupported_runtime`).
|
|
2320
|
+
content:
|
|
2321
|
+
application/json:
|
|
2322
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2323
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2324
|
+
'403':
|
|
2325
|
+
description: '`forbidden` — caller lacks `packs:publish` scope or the namespace claim.'
|
|
2326
|
+
content:
|
|
2327
|
+
application/json:
|
|
2328
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2329
|
+
'404':
|
|
2330
|
+
description: 'Host does not advertise `capabilities.packs.testMode.supported: true`, or the test-mode env-gate is unset.'
|
|
2331
|
+
content:
|
|
2332
|
+
application/json:
|
|
2333
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2334
|
+
'409':
|
|
2335
|
+
description: '`conflict` (or `version_conflict`) — `(name, version)` already published with different content.'
|
|
2336
|
+
content:
|
|
2337
|
+
application/json:
|
|
2338
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2339
|
+
get:
|
|
2340
|
+
tags: [packs-test]
|
|
2341
|
+
summary: Fetch a published test-catalog tarball.
|
|
2342
|
+
description: 'Mirror of `GET /v1/packs/{name}/-/{version}.tgz`. Returns the gzipped tarball bytes with `Content-Type: application/tar+gzip` and an `ETag: "sha256-..."` matching the manifest''s `tarballSha256`. The mirrored production path is registry-service surface (`registry-operations.md`), not defined in this host document (see the `packs-test` tag scope note).'
|
|
2343
|
+
operationId: getTestPackTarball
|
|
2344
|
+
responses:
|
|
2345
|
+
'200':
|
|
2346
|
+
description: Tarball bytes.
|
|
2347
|
+
content:
|
|
2348
|
+
application/tar+gzip:
|
|
2349
|
+
schema: { type: string, format: binary }
|
|
2350
|
+
'400':
|
|
2351
|
+
description: '`invalid_pack_name` or `invalid_version` — URL params malformed.'
|
|
2352
|
+
content:
|
|
2353
|
+
application/json:
|
|
2354
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2355
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2356
|
+
'403':
|
|
2357
|
+
description: '`forbidden` — caller lacks `packs:read` scope.'
|
|
2358
|
+
content:
|
|
2359
|
+
application/json:
|
|
2360
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2361
|
+
'404':
|
|
2362
|
+
description: 'Pack version not found in the test catalog (or host does not advertise `capabilities.packs.testMode.supported: true`).'
|
|
2363
|
+
content:
|
|
2364
|
+
application/json:
|
|
2365
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2366
|
+
/v1/packs-test/{name}/-/{version}:
|
|
2367
|
+
parameters:
|
|
2368
|
+
- $ref: '#/components/parameters/PackName'
|
|
2369
|
+
- $ref: '#/components/parameters/PackVersion'
|
|
2370
|
+
delete:
|
|
2371
|
+
tags: [packs-test]
|
|
2372
|
+
summary: Unpublish a test-catalog version (mirrors unpublish-window semantics).
|
|
2373
|
+
description: |
|
|
2374
|
+
Mirror of `DELETE /v1/packs/{name}/-/{version}` per
|
|
2375
|
+
`spec/v1/node-packs.md`. Returns `400 unpublish_window_expired`
|
|
2376
|
+
for versions older than the registry's unpublish window
|
|
2377
|
+
(default 72h). Test-mode implementations MAY shorten the
|
|
2378
|
+
window for tractable conformance fixtures but MUST surface
|
|
2379
|
+
the same error code. The mirrored production path is
|
|
2380
|
+
registry-service surface (`registry-operations.md`), not
|
|
2381
|
+
defined in this host document (see the `packs-test` tag
|
|
2382
|
+
scope note).
|
|
2383
|
+
operationId: deleteTestPackVersion
|
|
2384
|
+
responses:
|
|
2385
|
+
'204':
|
|
2386
|
+
description: Version successfully unpublished from the test catalog.
|
|
2387
|
+
'400':
|
|
2388
|
+
description: '`unpublish_window_expired`, `invalid_pack_name`, or `invalid_version`.'
|
|
2389
|
+
content:
|
|
2390
|
+
application/json:
|
|
2391
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2392
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2393
|
+
'403':
|
|
2394
|
+
description: '`forbidden` — caller lacks `packs:publish` scope.'
|
|
2395
|
+
content:
|
|
2396
|
+
application/json:
|
|
2397
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2398
|
+
'404':
|
|
2399
|
+
description: Version doesn't exist in the test catalog, or host does not advertise the test-mode capability.
|
|
2400
|
+
content:
|
|
2401
|
+
application/json:
|
|
2402
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2403
|
+
|
|
2404
|
+
/v1/packs-test/{name}/-/{version}.sig:
|
|
2405
|
+
parameters:
|
|
2406
|
+
- $ref: '#/components/parameters/PackName'
|
|
2407
|
+
- $ref: '#/components/parameters/PackVersion'
|
|
2408
|
+
get:
|
|
2409
|
+
tags: [packs-test]
|
|
2410
|
+
summary: Fetch the detached Ed25519 signature for a test-catalog pack.
|
|
2411
|
+
description: |
|
|
2412
|
+
Mirror of `GET /v1/packs/{name}/-/{version}.sig`. Returns the
|
|
2413
|
+
signature blob over `pack.json` for this version. MAY 302-redirect
|
|
2414
|
+
to a storage-backend signed URL. The mirrored production path is
|
|
2415
|
+
registry-service surface (`registry-operations.md`), not defined
|
|
2416
|
+
in this host document (see the `packs-test` tag scope note).
|
|
2417
|
+
operationId: getTestPackSignature
|
|
2418
|
+
responses:
|
|
2419
|
+
'200':
|
|
2420
|
+
description: Signature blob.
|
|
2421
|
+
content:
|
|
2422
|
+
application/octet-stream:
|
|
2423
|
+
schema: { type: string, format: binary }
|
|
2424
|
+
'302':
|
|
2425
|
+
description: Redirect to a storage-backend signed URL (clients SHOULD follow).
|
|
2426
|
+
headers:
|
|
2427
|
+
Location:
|
|
2428
|
+
schema: { type: string, format: uri }
|
|
2429
|
+
'400':
|
|
2430
|
+
description: '`invalid_pack_name` or `invalid_version` — URL params malformed.'
|
|
2431
|
+
content:
|
|
2432
|
+
application/json:
|
|
2433
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2434
|
+
'401': { $ref: '#/components/responses/Unauthenticated' }
|
|
2435
|
+
'403':
|
|
2436
|
+
description: '`forbidden` — caller lacks `packs:read` scope.'
|
|
2437
|
+
content:
|
|
2438
|
+
application/json:
|
|
2439
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2440
|
+
'404':
|
|
2441
|
+
description: |
|
|
2442
|
+
`signature_not_available` — version is missing, yanked,
|
|
2443
|
+
unsigned at publish time, OR the registry's storage backend
|
|
2444
|
+
is unwired. The four cases are intentionally
|
|
2445
|
+
indistinguishable per spec/v1/node-packs.md §"GET /v1/packs/{name}/-/{version}.sig".
|
|
2446
|
+
Also returned when the host does not advertise
|
|
2447
|
+
`capabilities.packs.testMode.supported: true`.
|
|
2448
|
+
content:
|
|
2449
|
+
application/json:
|
|
2450
|
+
schema: { $ref: '../schemas/error-envelope.schema.json' }
|
|
2451
|
+
|
|
2452
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2453
|
+
# COMPONENTS
|
|
2454
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2455
|
+
components:
|
|
2456
|
+
|
|
2457
|
+
securitySchemes:
|
|
2458
|
+
ApiKeyAuth:
|
|
2459
|
+
type: http
|
|
2460
|
+
scheme: bearer
|
|
2461
|
+
bearerFormat: API key
|
|
2462
|
+
description: |
|
|
2463
|
+
openwop API key. Format implementation-defined; reference impl uses `hk_`/`hk_test_` prefixes.
|
|
2464
|
+
Each key carries one or more scopes from the canonical vocabulary
|
|
2465
|
+
(`manifest:read`, `runs:create`, `runs:read`, `runs:cancel`,
|
|
2466
|
+
`artifacts:read`, `webhooks:manage`, `approvals:respond`, `audit:read`).
|
|
2467
|
+
See `auth.md`.
|
|
2468
|
+
|
|
2469
|
+
parameters:
|
|
2470
|
+
WorkflowId:
|
|
2471
|
+
in: path
|
|
2472
|
+
name: workflowId
|
|
2473
|
+
required: true
|
|
2474
|
+
schema: { type: string, minLength: 1, maxLength: 128 }
|
|
2475
|
+
|
|
2476
|
+
RunId:
|
|
2477
|
+
in: path
|
|
2478
|
+
name: runId
|
|
2479
|
+
required: true
|
|
2480
|
+
schema: { type: string, minLength: 1, maxLength: 128 }
|
|
2481
|
+
|
|
2482
|
+
IdempotencyKey:
|
|
2483
|
+
in: header
|
|
2484
|
+
name: Idempotency-Key
|
|
2485
|
+
required: false
|
|
2486
|
+
schema:
|
|
2487
|
+
type: string
|
|
2488
|
+
maxLength: 255
|
|
2489
|
+
description: |
|
|
2490
|
+
Per-mutation idempotency token (see `idempotency.md` Layer 1).
|
|
2491
|
+
Server caches `(tenantId, endpoint, key)` → response for ≥24h.
|
|
2492
|
+
Duplicate requests return the cached response with header
|
|
2493
|
+
`openwop-Idempotent-Replay: true`.
|
|
2494
|
+
|
|
2495
|
+
WorkspacePath:
|
|
2496
|
+
in: path
|
|
2497
|
+
name: path
|
|
2498
|
+
required: true
|
|
2499
|
+
schema:
|
|
2500
|
+
type: string
|
|
2501
|
+
pattern: '^[A-Za-z0-9][A-Za-z0-9._/-]{0,255}$'
|
|
2502
|
+
description: |
|
|
2503
|
+
RFC 0059 workspace-relative file path. Flat namespace with
|
|
2504
|
+
`/`-in-names; no `..`, no leading `/`. Matches
|
|
2505
|
+
`workspace-file.schema.json#path`.
|
|
2506
|
+
|
|
2507
|
+
WorkspacePrefix:
|
|
2508
|
+
in: query
|
|
2509
|
+
name: prefix
|
|
2510
|
+
required: false
|
|
2511
|
+
schema: { type: string, maxLength: 256 }
|
|
2512
|
+
description: RFC 0059. Optional prefix filter over the flat `path` namespace for `listWorkspaceFiles`.
|
|
2513
|
+
|
|
2514
|
+
WorkspaceVersion:
|
|
2515
|
+
in: query
|
|
2516
|
+
name: version
|
|
2517
|
+
required: false
|
|
2518
|
+
schema: { type: integer, minimum: 1 }
|
|
2519
|
+
description: |
|
|
2520
|
+
RFC 0059. When `capabilities.workspace.versioned: true`, request the
|
|
2521
|
+
historical snapshot at this version. Absent = latest.
|
|
2522
|
+
|
|
2523
|
+
IfMatch:
|
|
2524
|
+
in: header
|
|
2525
|
+
name: If-Match
|
|
2526
|
+
required: false
|
|
2527
|
+
schema: { type: string, maxLength: 255 }
|
|
2528
|
+
description: |
|
|
2529
|
+
RFC 0059 optimistic-concurrency token — the file's current `etag`.
|
|
2530
|
+
A `PUT` carrying a stale `If-Match` returns `409 workspace_conflict`.
|
|
2531
|
+
|
|
2532
|
+
PackName:
|
|
2533
|
+
in: path
|
|
2534
|
+
name: name
|
|
2535
|
+
required: true
|
|
2536
|
+
schema:
|
|
2537
|
+
type: string
|
|
2538
|
+
minLength: 3
|
|
2539
|
+
maxLength: 214
|
|
2540
|
+
description: Reverse-DNS pack name per `spec/v1/node-packs.md` §Naming (e.g. `vendor.acme.salesforce-tools`).
|
|
2541
|
+
|
|
2542
|
+
PackVersion:
|
|
2543
|
+
in: path
|
|
2544
|
+
name: version
|
|
2545
|
+
required: true
|
|
2546
|
+
schema:
|
|
2547
|
+
type: string
|
|
2548
|
+
pattern: '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?$'
|
|
2549
|
+
description: SemVer 2.0.0 version of the pack.
|
|
2550
|
+
|
|
2551
|
+
responses:
|
|
2552
|
+
Unauthenticated:
|
|
2553
|
+
description: Missing or invalid credential.
|
|
2554
|
+
content:
|
|
2555
|
+
application/json:
|
|
2556
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
2557
|
+
|
|
2558
|
+
Forbidden:
|
|
2559
|
+
description: Credential valid but lacks required scope or fails resource binding.
|
|
2560
|
+
content:
|
|
2561
|
+
application/json:
|
|
2562
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
2563
|
+
|
|
2564
|
+
NotFound:
|
|
2565
|
+
description: Resource doesn't exist or caller can't see it (do not leak existence).
|
|
2566
|
+
content:
|
|
2567
|
+
application/json:
|
|
2568
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
2569
|
+
|
|
2570
|
+
ValidationError:
|
|
2571
|
+
description: Request body or parameters malformed.
|
|
2572
|
+
content:
|
|
2573
|
+
application/json:
|
|
2574
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
2575
|
+
|
|
2576
|
+
RateLimited:
|
|
2577
|
+
description: Too many requests.
|
|
2578
|
+
headers:
|
|
2579
|
+
Retry-After:
|
|
2580
|
+
schema: { type: integer }
|
|
2581
|
+
content:
|
|
2582
|
+
application/json:
|
|
2583
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
2584
|
+
|
|
2585
|
+
schemas:
|
|
2586
|
+
|
|
2587
|
+
# Hoisted to first-class JSON Schemas in ../schemas/ so the SDK and
|
|
2588
|
+
# conformance suite can validate against the same source. The
|
|
2589
|
+
# in-line aliases below pull them via $ref so existing
|
|
2590
|
+
# `#/components/schemas/Error` references keep working.
|
|
2591
|
+
|
|
2592
|
+
Error:
|
|
2593
|
+
$ref: '../schemas/error-envelope.schema.json'
|
|
2594
|
+
|
|
2595
|
+
Capabilities:
|
|
2596
|
+
$ref: '../schemas/capabilities.schema.json'
|
|
2597
|
+
|
|
2598
|
+
# Pre-loaded so redocly's $ref resolver registers them at lint time.
|
|
2599
|
+
# capabilities.schema.json `$ref`s prompt-kind.schema.json by its
|
|
2600
|
+
# canonical openwop.dev URL — redocly resolves absolute URIs against
|
|
2601
|
+
# already-loaded `$id`s, so the schema must be pulled in here even
|
|
2602
|
+
# though no operation references it directly. See RFC 0027 §A.
|
|
2603
|
+
PromptKind:
|
|
2604
|
+
$ref: '../schemas/prompt-kind.schema.json'
|
|
2605
|
+
|
|
2606
|
+
PromptTemplate:
|
|
2607
|
+
$ref: '../schemas/prompt-template.schema.json'
|
|
2608
|
+
|
|
2609
|
+
PromptRef:
|
|
2610
|
+
$ref: '../schemas/prompt-ref.schema.json'
|
|
2611
|
+
|
|
2612
|
+
RunSnapshot:
|
|
2613
|
+
$ref: '../schemas/run-snapshot.schema.json'
|
|
2614
|
+
|
|
2615
|
+
RunClaimConflict:
|
|
2616
|
+
description: |
|
|
2617
|
+
Specialization of the canonical `ErrorEnvelope` shape for
|
|
2618
|
+
`run_already_active`. Conflict metadata lives under `details`
|
|
2619
|
+
so the top-level error shape remains `{error, message, details?}`.
|
|
2620
|
+
allOf:
|
|
2621
|
+
- $ref: '#/components/schemas/Error'
|
|
2622
|
+
- type: object
|
|
2623
|
+
required: [error, message, details]
|
|
2624
|
+
properties:
|
|
2625
|
+
error:
|
|
2626
|
+
type: string
|
|
2627
|
+
enum: [run_already_active]
|
|
2628
|
+
message: { type: string }
|
|
2629
|
+
details:
|
|
2630
|
+
type: object
|
|
2631
|
+
required: [activeRunId, activeHost]
|
|
2632
|
+
properties:
|
|
2633
|
+
activeRunId: { type: string }
|
|
2634
|
+
activeHost:
|
|
2635
|
+
type: string
|
|
2636
|
+
enum: [browser, cloud]
|
|
2637
|
+
retryAfter:
|
|
2638
|
+
type: integer
|
|
2639
|
+
description: 'Seconds. Mirrors the `Retry-After` header.'
|
|
2640
|
+
|
|
2641
|
+
UnsupportedStreamMode:
|
|
2642
|
+
description: |
|
|
2643
|
+
Specialization of the canonical `ErrorEnvelope` shape (see
|
|
2644
|
+
`error-envelope.schema.json`) for the `unsupported_stream_mode`
|
|
2645
|
+
case. The `supported` array lives in `details` per the canonical
|
|
2646
|
+
envelope's contextual-data slot, NOT at the top level. SDK
|
|
2647
|
+
consumers using a generic ErrorEnvelope parser will find the
|
|
2648
|
+
list under `details.supported` regardless of which validator
|
|
2649
|
+
fired.
|
|
2650
|
+
allOf:
|
|
2651
|
+
- $ref: '#/components/schemas/Error'
|
|
2652
|
+
- type: object
|
|
2653
|
+
required: [error, message, details]
|
|
2654
|
+
properties:
|
|
2655
|
+
error:
|
|
2656
|
+
type: string
|
|
2657
|
+
enum: [unsupported_stream_mode]
|
|
2658
|
+
message: { type: string }
|
|
2659
|
+
details:
|
|
2660
|
+
type: object
|
|
2661
|
+
required: [supported]
|
|
2662
|
+
properties:
|
|
2663
|
+
supported:
|
|
2664
|
+
type: array
|
|
2665
|
+
items: { type: string, enum: [values, updates, messages, debug] }
|
|
2666
|
+
|
|
2667
|
+
TestPackPublishRecord:
|
|
2668
|
+
description: |
|
|
2669
|
+
Response body for a successful publish against the test-mode
|
|
2670
|
+
registry namespace (RFC 0025). Mirror of the production publish
|
|
2671
|
+
record returned by `PUT /v1/packs/{name}/-/{version}.tgz`.
|
|
2672
|
+
type: object
|
|
2673
|
+
required: [name, version, tarballSha256, publishedAt]
|
|
2674
|
+
properties:
|
|
2675
|
+
name:
|
|
2676
|
+
type: string
|
|
2677
|
+
description: Reverse-DNS pack name as PUT'd.
|
|
2678
|
+
version:
|
|
2679
|
+
type: string
|
|
2680
|
+
description: SemVer 2.0.0 version as PUT'd.
|
|
2681
|
+
tarballSha256:
|
|
2682
|
+
type: string
|
|
2683
|
+
pattern: '^sha256-[A-Za-z0-9+/=]+$'
|
|
2684
|
+
description: Server-computed SHA-256 over the uploaded tarball bytes.
|
|
2685
|
+
publishedAt:
|
|
2686
|
+
type: string
|
|
2687
|
+
format: date-time
|
|
2688
|
+
signed:
|
|
2689
|
+
type: boolean
|
|
2690
|
+
description: Whether a sibling `.sig` signature blob was persisted.
|
|
2691
|
+
signingMethod:
|
|
2692
|
+
type: string
|
|
2693
|
+
enum: [sigstore, manual, none]
|