Prepare. Inspect. Commit.
Work SDK turns a provider mutation into a reviewable value before it becomes a side effect. Integrity, optimistic concurrency, and idempotency each protect a different failure boundary.
Why a protocol?
A direct API call combines intent, provider translation, authorization, and an irreversible effect. Agents are especially vulnerable to retry ambiguity and stale context. Work SDK separates decision time from mutation time.
Prepared plan anatomy
type PreparedWorkChange =
| { action: "create"; input: CreateWorkItemInput; targetId?: never }
| { action: "update"; input: UpdateWorkItemInput;
targetId: string; current: WorkItem; expectedRevision: string }
| { action: "comment"; input: AddCommentInput;
targetId: string; current: WorkItem; expectedRevision: string };
// Every variant also contains provider, changes, warnings, summary,
// preparedAt, id, and an integrity fingerprint.Plans are serializable and contain no credentials. The current snapshot explains the diff; expectedRevision makes the later commit conditional.
Integrity fingerprint
The fingerprint covers every signed plan field. If application code or an agent mutates the reviewed input, changes, warnings, target, or revision, commit rejects the plan before any provider request.
The fingerprint detects accidental mutation. It is not a user-authentication signature and should not be treated as one across untrusted boundaries.
Concurrency guarantees
Update and comment plans capture the item's opaque revision. Commit re-reads the item and fails closed if it changed. capabilities.concurrency reports whether the final provider mutation is atomic, uses a best-effort preflight, or has no protection. Azure DevOps updates use an atomic JSON Patch test /rev; GitHub, GitLab, Linear, and Jira retain a small read-to-write race window.
try {
await work.commit(change, { idempotencyKey });
} catch (error) {
if (error instanceof WorkConflictError) {
// Never patch the old plan or force the write.
const replacement = await work.prepareUpdate(change.targetId!, change.input);
return requestApproval(replacement);
}
throw error;
}Idempotency
The default memory store atomically coordinates retries inside one process. Serverless, clustered, and job systems must supply a durable store with an atomic claim. Keys should identify the business event, for example github:webhook:delivery-123:comment, not the attempt. Work SDK binds each key to the normalized provider, action, target, and input.
replayed: true.WorkInFlightError; do not start a second write.WorkAmbiguousCommitError and require reconciliation.WorkConflictError before a provider mutation.Durability alone is insufficient. A store implemented as separate get and set operations can still duplicate writes across workers.
Warnings and approval
Warnings describe lossy mappings, ambiguous values, unsupported fields, or provider limitations. Commit requires acceptWarnings: true when warnings exist, forcing the caller to acknowledge them explicitly.
Acceptance means “the caller reviewed this risk.” It does not make an impossible provider operation possible; an adapter can still reject invalid or unsupported input.