Tarski/ docsJoin the waitlist

Effects & reconciliation

How Tarski touches the world — declared capabilities, admission identity, retry policies, the effect lifecycle, work queues, and explicit reconciliation.

Effects are downstream of semantic evaluation, always:

proposal.* → decision.approved.* → intent.* → effect request → attempt → receipt observation

Approved decisions derive intents; effect authority admits requests; the runtime executes declared capabilities; and results return only as receipt observations that re-enter the lineage as evidence. Guest code cannot mutate facts, append observations directly, or use undeclared ambient I/O.

Capabilities

Capability Purpose
http.fetch Declared outbound HTTP
llm.complete Explicit model calls for LLM-assisted agents
blob.put / blob.get Content-addressed large payload storage
timer.schedule A future timer observation
log.dev Developer diagnostics only — never canonical state

Capabilities are declared in tarski.toml and bound to intent relations. Admission identity is the lineage plus the intent relation name plus declared identity key values — which is what makes retries and crash recovery resolvable.

If a live binding’s credential reference cannot be resolved, the effect blocks with typed http.credential.unresolved before the network is opened — no receipt is appended, and nothing silently substitutes a deterministic provider.

Retries

Idempotent effects may auto-retry when the runtime classifies retry as safe. Non-idempotent or uncertain attempts enter reconciliation instead — policy never overrides the runtime’s safety classification.

Retry policies are declared per intent binding: fixed or exponential backoff, initial and maximum delays, optional deterministic jitter, and exhaustion bounds (max attempts and/or elapsed time) with on_exhausted = "failed" or manual reconciliation. Resolved policies are canonicalized and digested at admission — later manifest edits can never rewrite the policy an old decision ran under.

The effect lifecycle family

The runtime populates a reserved relation family your rules can read (never declare): effect.queued, effect.in_flight, effect.succeeded, typed effect.failed, effect.blocked, effect.reconcile_required, effect.conflict, plus grouping views effect.open and effect.terminal.

Rules that derive an intent at head H can read that effect’s lifecycle evidence only at a later head — same-head feedback loops are structurally impossible.

Work queues

Work queues are operational dispatch control for already-admitted requests — “when may this start?”, never “may this happen?”. Queue policy (concurrency, partitions, ordering, lease timing, rate limits, saturation behavior) is frozen at admission with its own digest; operators adjust capacity by appending durable queue-control records, not by editing manifests. Inspect with:

tarski work-queue list
tarski work-queue inspect

Reconciliation

When an effect attempt is ambiguous — a crash mid-flight, an uncertain provider — the runtime never silently guesses. The attempt parks as reconcile_required, and an operator resolves it explicitly:

tarski reconcile inspect --session latest
tarski reconcile resolve <attempt-id> --outcome <succeeded|failed|retry>

The resolution appends as an observation, so the decision is part of the lineage — auditable, replayable, and visible in provenance like everything else. Manual retry keeps the original attempt counter and frozen policy metadata.

Typed HTTP receipts

Plugin-owned http.fetch bindings may declare a receipt_kind plus a request template, producing typed, schema-validated receipt observations (e.g. a product-page fetch result) instead of the generic effect.result. App-owned HTTP bindings emit generic effect.result receipts in V1. result_kind belongs to llm.complete only. See Plugins.