Extensions for agents

Every extension on the platform ships a machine-readable agent contract — a required manifest block (ADR 0027 §8): summaryEN, an ordered setup recipe, extension-specific ops, and docs anchors. extension.install refuses a manifest without a valid contract, so "an extension agents cannot use" does not exist here. Each catalog page renders its extension's contract as a generated For agents section; capability-derived ops (refund for a refund-capable payment provider, offers/book/label/track for cargo) come from the platform's classification table and never need declaring twice.

Setup is a recipe, not folklore

The contract's setup is the numbered order that works: install (consent) → secrets → configure → enable → verify. Follow it literally — each step names the exact command, config pointer or op. Two things to internalize:

Readiness: extensions.ops.get

GET /v1/extensions/{ext}/ops

extensions.ops.get answers the contract plus live readiness for this store: every op with ready: true|false and, when blocked, exactly why. The blockedBy vocabulary is closed:

Loop on it: read readiness → resolve what you can (install/configure/enable proposals) → tell the owner what only they can do → verify. Secrets appear as keys only — the platform never returns secret values to anyone. CLI: mozaik ext ops <extensionId> (ext).

Secrets are owner-only

Ajan tokens can never hold secrets:write, and secret.set is owner-policy — this is structural, not advisory (Tokens). When a setup step says "owner enters the API key in the admin panel", the correct agent behaviour is to surface it as a clear ask ("Eklentiler → Geliver → Geliver API Anahtarı") and continue with what is unblocked. Never ask the merchant to paste credentials into chat: a value that reaches you cannot become a sealed write-only secret by any path you control.

Provider-driven inbound is not callable

Webhooks (/v1/ext/{id}/wh/{token}/{storeId}) and manifest jobs are the provider's push and the platform's schedule — they appear in the contract's inbound list precisely so you know they are not yours to call. Do not simulate a webhook to "advance" a shipment or payment; the ingestion route verifies provenance and will refuse you. When an order seems stuck waiting on a provider, the agent-shaped move is the polling op the contract gives you (orders.shipment.update for cargo) or a note to the owner — not forged inbound traffic.

Worked example

mozaik.geliver — install (PII consent: buyer name/phone/address flow to Geliver) → owner sets cargo.geliver.api_token → run op sender-address via ext.cargo.sender (works while still disabled; records the sender profile into config) → enable → verify with the offers op (orders.cargo.offers, a quote — free to call, mutates nothing). After that, book proposes the actual shipment.

Generated from the live platform registries at build time — reference pages cannot go stale. Markdown variant: /agents-extensions.md