Compatibility: Pactmark 0.1.x. The current public authoring facade exposes
kind: "read"
operations. Write-effect authoring, decision challenges and reconciliation commands exist in the
runtime surface and are being brought to the public facade — see
Limits.A tool is a declaration plus a function
Figure 1. Everything on the left contributes to the tool’s registration digest. That is why a tool cannot quietly become more dangerous while keeping an old grant.id is constrained to a namespace.name@version shape, and implementationVersion is
separate on purpose: the contract version tells consumers what to expect, the implementation version
makes a behaviour change visible even when the contract is unchanged.
What the execution context gives you
SafeRunContext
tenantId, runId, stepId, purposeCode, dataClass — enough to make a correct decision, and
deliberately not enough to identify a human.EgressHttpClient
The only network client a tool should use. It applies the declared allowlist, redirect policy, TLS
verification and byte/time limits.
ArtifactWriter
Writes bytes and returns
{ artifactId, contentDigest }. Content addressing happens here, not
later.AbortSignal
Cancellation and deadline propagation. A tool that ignores it will be bounded by
timeoutMs
anyway, but it will waste the budget first.Effects: the interesting half
A read observes. An effect changes something outside the run — and once it might have happened, your options narrow permanently. Figure 2. The strategy is registered on the tool, not chosen at failure time. That ordering is the whole safety property: you cannot decide it is safe to retry after you already want it to be.Why “retry on timeout” is a bug
A timeout tells you the response did not arrive. It tells you nothing about whether the request was processed. Systems that retry on timeout are correct only when every target is idempotent — which is an assumption, not a fact. Pactmark makes you state the assumption up front:native
You are claiming the target is idempotent for this exact effect key. Repeating is safe.
transactional
The effect commits together with local state, so a rollback removes it.
reconcilable
You cannot repeat it, but you can look it up afterwards and learn what happened.
none
No safe repetition exists. The effect parks and waits for an authorised human decision.
The effect ledger
Around every external boundary, Pactmark writes preparation, acknowledgement and reconciliation state.EffectPrepared carries an effectKey and the registered strategy; EffectDispatched
carries an attempt number; EffectAcknowledged carries the acknowledgement and a result digest.
When the outcome is unknown, EffectUncertain and then EffectNeedsReconciliation are recorded —
and the schema forces effectMayHaveOccurred: true. You cannot record uncertainty while implying
safety.
Resolution has exactly two shapes:
abandon_uncertain raises KAF_EFFECT_ABANDONED_UNCERTAIN for anything that later depends on it.
That is intentional friction.
Compensation is a new authorised run
Compensation is not “undo”.CompensationRequested starts a separate compensation run with its
own authority, its own WorkOrder and its own evidence. It is a business action that happens to
reverse another one, and it is authorised as such.
Defining tools
A practical walkthrough with egress, scopes and testing.
Incident recovery
Containment, classification and reconciliation when something has gone wrong.