OpenWOP openwop.dev
gRPC transport

OpenWOP — gRPC service definition

OpenWOP defines an optional gRPC transport profile alongside the primary REST + SSE surface. A host MAY advertise the gRPC profile in /.well-known/openwop; clients MAY use it interchangeably with REST for any endpoint covered by the proto. The two transports MUST surface identical semantics — the conformance suite enforces parity. See grpc-transport.md for the normative claims.

Source: api/grpc/openwop.proto in the repo.

// openwop v1 — gRPC service definition (optional alternative to REST + SSE).
//
// Status: FINAL v1 (2026-05-12). Closes R3 in rest-endpoints.md
// §"Open spec gaps". Hosts that advertise `capabilities.grpc.supported:
// true` expose this service in addition to (NOT instead of) the
// REST + SSE surface. Per-method semantics are normatively defined by
// the corresponding REST operation in `api/openapi.yaml`; this file
// supplies the wire-shape only.
//
// Service-name canonical: openwop.v1.Engine (one service per major).
// Method names: PascalCase form of `api/openapi.yaml` operationIds.
// Error mapping: see `spec/v1/grpc-transport.md` §"Error mapping".
//
// Message shapes mirror the JSON Schemas — full shape definitions are
// abridged here for readability; reference impls SHOULD `import` each
// JSON Schema's corresponding `.proto` snippet from a paired
// `schemas/grpc/<name>.proto` once those land (deferred to v1.x). For
// the v1 reference, hosts MAY hand-roll the messages from the JSON
// Schema definitions; the wire surface is byte-equivalent across both
// projections.

syntax = "proto3";

package openwop.v1;

import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/openwop/openwop/api/grpc/openwopv1";
option java_package = "dev.openwop.api.v1";
option csharp_namespace = "Openwop.V1";

// ─────────────────────────────────────────────────────────────────────
// Service — one per protocol major version.
// ─────────────────────────────────────────────────────────────────────
service Engine {
  // Discovery — 1:1 with REST `GET /.well-known/openwop`.
  // Unauthenticated.
  rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse);

  // Workflow + Run lifecycle.
  rpc GetWorkflow(GetWorkflowRequest) returns (GetWorkflowResponse);
  rpc CreateRun(CreateRunRequest) returns (CreateRunResponse);
  rpc GetRun(GetRunRequest) returns (GetRunResponse);
  rpc CancelRun(CancelRunRequest) returns (CancelRunResponse);
  rpc BulkCancelRuns(BulkCancelRunsRequest) returns (BulkCancelRunsResponse);
  rpc ForkRun(ForkRunRequest) returns (ForkRunResponse);
  rpc PauseRun(PauseRunRequest) returns (PauseRunResponse);
  rpc ResumeRun(ResumeRunRequest) returns (ResumeRunResponse);

  // Events — server-streaming replaces SSE.
  rpc StreamRunEvents(StreamRunEventsRequest) returns (stream RunEventEnvelope);

  // HITL — interrupt resolution.
  rpc ResolveInterruptByRun(ResolveInterruptByRunRequest) returns (ResolveInterruptResponse);
  rpc ResolveInterruptByToken(ResolveInterruptByTokenRequest) returns (ResolveInterruptResponse);
  rpc InspectInterruptByToken(InspectInterruptByTokenRequest) returns (InspectInterruptResponse);

  // Artifacts + Webhooks + Audit verify.
  rpc GetArtifact(GetArtifactRequest) returns (GetArtifactResponse);
  rpc RegisterWebhook(RegisterWebhookRequest) returns (RegisterWebhookResponse);
  rpc UnregisterWebhook(UnregisterWebhookRequest) returns (google.protobuf.Empty);
  rpc VerifyAuditLog(VerifyAuditLogRequest) returns (VerifyAuditLogResponse);
}

// ─────────────────────────────────────────────────────────────────────
// Messages — abridged. Each message mirrors the corresponding REST
// request/response body; field shapes use Struct for sub-trees that
// don't yet have hand-rolled Protobuf representations. A future v1.x
// minor expands every Struct into its typed Protobuf message.
// ─────────────────────────────────────────────────────────────────────

message GetCapabilitiesRequest {}

message GetCapabilitiesResponse {
  // Body matches schemas/capabilities.schema.json.
  google.protobuf.Struct capabilities = 1;
}

message GetWorkflowRequest {
  string workflow_id = 1;
}

message GetWorkflowResponse {
  // Body matches schemas/workflow-definition.schema.json.
  google.protobuf.Struct workflow = 1;
}

message CreateRunRequest {
  string workflow_id = 1;
  google.protobuf.Struct inputs = 2;       // schemas/run-options.schema.json §inputs
  google.protobuf.Struct configurable = 3; // schemas/run-options.schema.json §configurable
  repeated string tags = 4;
  google.protobuf.Struct metadata = 5;
  string idempotency_key = 6;              // Idempotency-Key, optional
}

message CreateRunResponse {
  string run_id = 1;
  string status = 2;
}

message GetRunRequest {
  string run_id = 1;
}

message GetRunResponse {
  // Body matches schemas/run-snapshot.schema.json.
  google.protobuf.Struct snapshot = 1;
}

message CancelRunRequest {
  string run_id = 1;
  string reason = 2;
}

message CancelRunResponse {
  string run_id = 1;
  string status = 2;
}

message BulkCancelRunsRequest {
  repeated string run_ids = 1;
  string reason = 2;
}

message BulkCancelRunResult {
  string run_id = 1;
  bool ok = 2;
  string status = 3;                       // "cancelled" / "cancelling" when ok=true
  google.protobuf.Struct error = 4;        // error-envelope.schema.json when ok=false
}

message BulkCancelRunsResponse {
  repeated BulkCancelRunResult results = 1;
}

message ForkRunRequest {
  string run_id = 1;
  int64 from_seq = 2;
  string mode = 3;                         // "replay" | "branch"
  google.protobuf.Struct overlay = 4;      // optional run-options overlay
}

message ForkRunResponse {
  string forked_run_id = 1;
  string status = 2;
}

message PauseRunRequest {
  string run_id = 1;
  string reason = 2;
  string drain_policy = 3;                 // "immediate" | "drain-current-node"
}

message PauseRunResponse {
  string run_id = 1;
  string status = 2;
  google.protobuf.Timestamp paused_at = 3;
}

message ResumeRunRequest {
  string run_id = 1;
  string reason = 2;
}

message ResumeRunResponse {
  string run_id = 1;
  string status = 2;
  google.protobuf.Timestamp resumed_at = 3;
}

message StreamRunEventsRequest {
  string run_id = 1;
  int64 last_sequence = 2;                 // -1 = from start
  repeated string stream_modes = 3;        // subset of stream-modes.md
  int32 buffer_ms = 4;
}

message RunEventEnvelope {
  string event_id = 1;
  int64 seq = 2;
  string run_id = 3;
  string type = 4;
  string node_id = 5;
  google.protobuf.Struct payload = 6;      // run-event-payloads.schema.json §<type>
  google.protobuf.Timestamp timestamp = 7;
  string causation_id = 8;                 // optional, run-event.schema.json §causationId
}

message ResolveInterruptByRunRequest {
  string run_id = 1;
  string node_id = 2;
  google.protobuf.Struct resume_value = 3; // shape per InterruptPayload.resumeSchema
}

message ResolveInterruptByTokenRequest {
  string token = 1;
  google.protobuf.Struct resume_value = 2;
}

message InspectInterruptByTokenRequest {
  string token = 1;
}

message ResolveInterruptResponse {
  string run_id = 1;
  string node_id = 2;
  string status = 3;
}

message InspectInterruptResponse {
  // Body matches schemas/suspend-request.schema.json.
  google.protobuf.Struct interrupt = 1;
}

message GetArtifactRequest {
  string run_id = 1;
  string artifact_id = 2;
}

message GetArtifactResponse {
  string artifact_id = 1;
  string content_type = 2;
  bytes content = 3;
}

message RegisterWebhookRequest {
  string url = 1;
  repeated string event_types = 2;
  string secret = 3;                       // operator-supplied HMAC secret
}

message RegisterWebhookResponse {
  string webhook_id = 1;
}

message UnregisterWebhookRequest {
  string webhook_id = 1;
}

message VerifyAuditLogRequest {
  int64 from_seq = 1;
  int64 to_seq = 2;
}

message VerifyAuditLogResponse {
  // Body matches schemas/audit-verify-result.schema.json.
  google.protobuf.Struct result = 1;
}