Semogram Docs
Workspace managementWrite controls

Governed actions

Reference published source-write contracts, action requests, approval policies, lifecycle routes, execution receipts and change feeds for supported targets.

Governed actions publish versioned mutation contracts. A caller submits a request, eligible members approve it where required, and execution produces a receipt. The current adapter guarantee is iceberg_atomic_receipt through @craven/iceberg for source_write targets. This is not a generic wrapper for every pipeline destination or ontology write.

Contract example

In your connected assistant, ask the assistant:

Prepare this governed-action contract without publishing or executing it. Contract version: 1; Name: warehouse-forecast-append; Description: Append reviewed forecast rows; Input schema / Type: object; Output schema / Type: object; Required permissions: ["data:write"]; Approval policy / Mode: required; Approval policy / Roles: ["owner", "admin"]; Approval policy / Minimum approvals: 1; Approval policy / Self approval: Disabled; Preconditions / Required input paths: []; Idempotency / Required: Enabled; Idempotency / Scope: caller_action; Idempotency / Conflict: reject; Concurrency / Mode: reject; Concurrency / Key input paths: []; Receipt semantics / Adapter guarantee: iceberg_atomic_receipt; Receipt semantics / Uncertain outcome: reconcile_before_retry; Receipt semantics / Exactly once: Disabled; Target / Kind: source_write; Target / Data endpoint id: 11111111-1111-4111-8111-111111111111. Use the actual accessible resources and required enclosing definition. Show the proposed settings and validate them before saving or executing.

This request describes the example’s intent; review the generated contract and any required permissions. It does not create missing resources or make an unsupported operation available.

Use a workspace API key with policy:manage. Set SEMOGRAM_API_KEY in your shell; replace resource placeholders with real IDs. This is an HTTP resource request, not an MCP JSON-RPC message.

HTTP API request
curl --request POST "https://platform.semogram.com/api/v1/projects/<PROJECT_ID_UUID>/actions" \
  --header "Authorization: Bearer ${SEMOGRAM_API_KEY}" \
  --header "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "slug": "warehouse-forecast-append",
  "contract": {
    "contractVersion": 1,
    "name": "warehouse-forecast-append",
    "description": "Append reviewed forecast rows",
    "inputSchema": {
      "type": "object"
    },
    "outputSchema": {
      "type": "object"
    },
    "requiredPermissions": [
      "data:write"
    ],
    "approvalPolicy": {
      "mode": "required",
      "roles": [
        "owner",
        "admin"
      ],
      "minimumApprovals": 1,
      "selfApproval": false
    },
    "preconditions": {
      "requiredInputPaths": []
    },
    "idempotency": {
      "required": true,
      "scope": "caller_action",
      "conflict": "reject"
    },
    "concurrency": {
      "mode": "reject",
      "keyInputPaths": []
    },
    "receiptSemantics": {
      "adapterGuarantee": "iceberg_atomic_receipt",
      "uncertainOutcome": "reconcile_before_retry",
      "exactlyOnce": false
    },
    "target": {
      "kind": "source_write",
      "dataEndpointId": "11111111-1111-4111-8111-111111111111"
    }
  }
}
JSON

Use an authenticated, initialized MCP client. Replace resource placeholders with accessible IDs.

MCP request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "action_publish",
    "arguments": {
      "projectId": "<PROJECT_ID_UUID>",
      "slug": "warehouse-forecast-append",
      "contract": {
        "contractVersion": 1,
        "name": "warehouse-forecast-append",
        "description": "Append reviewed forecast rows",
        "inputSchema": {
          "type": "object"
        },
        "outputSchema": {
          "type": "object"
        },
        "requiredPermissions": [
          "data:write"
        ],
        "approvalPolicy": {
          "mode": "required",
          "roles": [
            "owner",
            "admin"
          ],
          "minimumApprovals": 1,
          "selfApproval": false
        },
        "preconditions": {
          "requiredInputPaths": []
        },
        "idempotency": {
          "required": true,
          "scope": "caller_action",
          "conflict": "reject"
        },
        "concurrency": {
          "mode": "reject",
          "keyInputPaths": []
        },
        "receiptSemantics": {
          "adapterGuarantee": "iceberg_atomic_receipt",
          "uncertainOutcome": "reconcile_before_retry",
          "exactlyOnce": false
        },
        "target": {
          "kind": "source_write",
          "dataEndpointId": "11111111-1111-4111-8111-111111111111"
        }
      }
    }
  }
}

Replace the illustrative endpoint UUID with an accessible, supported endpoint. Choose meaningful input/output schemas rather than leaving them unconstrained. Required input paths (up to 100) and concurrency key paths (up to 20) use JSON Pointers. Required permissions include data:write, data:delete, or data:maintain.

Request and approval

Source-write input includes contractVersion: 1, an operation (append, upsert, update, or delete), and expectedSourceSnapshot from the immediately preceding source read. Append/upsert supply rows; update supplies predicates and set values; delete supplies predicates. The addressed endpoint and approved policy determine identity and target; callers cannot override them.

Request idempotency keys are 8–200 characters. Reuse a key only for the exact same business operation and input. Approval decisions are approved/rejected with a non-empty reason up to 2000 characters. Required policies specify eligible owner/admin roles, 1–10 approvals, and self-approval behavior.

Source-write enablement, policy approval, actor grants, and action-request approval are distinct. API callers must have the required scopes and accountable current membership; possession of a key alone does not satisfy approval rules.

Lifecycle routes

All routes are under /api/v1/projects/<PROJECT_ID>.

RouteOperation
GET /actionsList actions
POST /actionsPublish an action with slug and contract
GET /actions/<ACTION_ID>Inspect an action/version
POST /actions/<ACTION_ID>/requestsSubmit input and idempotency key
GET /action-requests/<REQUEST_ID>Inspect request
POST /action-requests/<REQUEST_ID>/reviewApprove or reject
POST /action-requests/<REQUEST_ID>/executeExecute
POST /action-requests/<REQUEST_ID>/reconcileReconcile uncertain execution

Receipts

Receipts include action/request/version IDs, adapter, operation ID, request hash, status (succeeded, failed, uncertain), nullable source-write result, and recovery instructions. Result counts are attempted, inserted, updated, and deleted; there is no generic rowsWritten result field.

An uncertain outcome requires reconciliation before retrying. The contract explicitly makes no exactly-once claim.

Change feed

POST /changes/pull takes consumer, limit (default 25, maximum 100), optional numeric-string afterSequence, and topic filters: assertion.revision, identity.correction, query.completed, action.committed. POST /changes/ack acknowledges up to 100 event UUIDs for that consumer. Failure reporting and dead-letter inspection are also available; do not acknowledge a failed downstream effect as successfully consumed.

See Write policies.