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.
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"
}
}
}
JSONUse an authenticated, initialized MCP client. Replace resource placeholders with accessible IDs.
{
"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>.
| Route | Operation |
|---|---|
GET /actions | List actions |
POST /actions | Publish an action with slug and contract |
GET /actions/<ACTION_ID> | Inspect an action/version |
POST /actions/<ACTION_ID>/requests | Submit input and idempotency key |
GET /action-requests/<REQUEST_ID> | Inspect request |
POST /action-requests/<REQUEST_ID>/review | Approve or reject |
POST /action-requests/<REQUEST_ID>/execute | Execute |
POST /action-requests/<REQUEST_ID>/reconcile | Reconcile 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.