Known limitations

What mnd8t does not do, stated plainly. Read this before you rely on it — knowing where the boundary sits is part of using the product correctly.

Status: sandbox developer preview

mnd8t is a developer preview and not yet a production service. It does not support use with real funds, and its terms do not permit it. mnd8t never moves money itself, so it cannot see whether your executor spends on a testnet or a mainnet, and it cannot stop it doing either. The adapters provided are a simulated account and one EVM testnet adapter, and nothing here has been load-tested. Read every section below on that footing.

What a customer can actually do today:

Available now Not available yet
Author, version, publish and revoke mandates Use with real funds — unsupported and not permitted by the terms
Run in shadow mode against real traffic and compare decisions Production SLAs, load-tested throughput, capacity guarantees
Run in enforce mode against a simulated wallet or an EVM testnet Any mainnet or bank-rail adapter
Deterministic APPROVE / REJECT / ESCALATE with full reason sets Enterprise SSO, billing, mobile app, self-service org invites, open sign-up (invited addresses only)
Human approval links and the approvals dashboard Approval emails without a provider (Resend is supported)
Signed, independently verifiable evidence receipts Compliance screening of any kind (KYC/AML/sanctions)
Single-use authorisation artifacts for your own executor mnd8t executing anything on your behalf, ever — by design
Verify whether a mandate's objective was fulfilled, against evidence you supply Evidence mnd8t fetches or checks itself — no carrier, merchant, bank or ERP integrations

The honest use for it right now is evaluation: wire an agent up in shadow mode, see what the policy would have decided against your real traffic, and run the full execution loop end to end on a testnet. Putting real customer money behind it requires the review in SECURITY.md, which has not been done.

What mnd8t deliberately does not do

These are not gaps waiting to be filled. They define the service.

  • mnd8t does not execute. It decides whether a proposed action is authorised and issues a signed authorisation artifact. Submitting the transaction is yours, or your regulated provider's. There is no execution code path in the service.
  • mnd8t does not hold assets or keys. No custody, no key management, no wallet. Your execution credentials never reach it.
  • mnd8t does not accept, route or price orders. It does not select an asset, counterparty, venue, exchange rate or execution time.
  • mnd8t does not perform compliance screening. No KYC, AML, sanctions or fraud checks. authority_status records your assertion about who you authorise paying; external_checks stores results from your own provider exactly as supplied, and verifies none of them.
  • mnd8t does not validate legal authority. A delegator attestation is a recorded assertion. mnd8t evidences that someone claimed the authority; it cannot certify they held it.
  • mnd8t does not verify identity attestations. An AFSP or other identity / session attestation presented with a decision is recorded, with a digest of the token, and checked for validity window, issuer, protocol and agent binding when the mandate asks. Its signature is not checked: the record says PRESENTED_UNVERIFIED. Verify it in your admission layer before calling mnd8t.
  • AFSP assertion export is a prototype. It is off by default (ENABLE_AFSP_ASSERTIONS) and implements a draft extension that AFSP has not adopted. The Servicing Intent field names are provisional until AFSP publishes a normative format. Only ISO 4217 currency amounts can be asserted.
  • mnd8t does not convert currencies. You supply the amount already normalised into the mandate's currency, with provenance. The engine evaluates only that figure.
  • An Authority Record proves a decision, not an outcome. It shows which mandate version, agent and action were evaluated and what mnd8t decided. It does not show that the payment was executed, settled or delivered. A record stays valid after its mandate is revoked; a valid record is not evidence that the agent is authorised now.
  • The action hash compares exact values. It applies no normalisation, so an executor whose instruction spells a field differently (case, Unicode form, a reference with a trailing space) gets a mismatch. Send mnd8t the values you will execute.
  • Nothing here is a compliance certification. Evidence receipts prove what was decided and by whose authority. Whether that satisfies a given regulation is a question for your own advisers.

What this makes you responsible for

  • The accuracy of your valuations. mnd8t trusts the policy amount you send. It fetches no exchange rates, so if the conversion is wrong — or if something that can influence it wants the limit not to bind — the decision is made against the wrong number. Mitigate it with asset-denominated limits (per_transaction.by_asset, asset_budgets), which are evaluated against the quantity that actually moves and cannot be affected by a valuation. For a budget that aggregates across assets, set require_asserted_valuation on the mandate: the figure must then come from a credential holding valuations:assert, which an agent key does not carry. That relocates the trust rather than creating it — an asserting backend sharing a host with the agent is no safer — and mnd8t still does not check whether the number is right, only that the agent did not choose it.
  • Reporting execution honestly. Confirmations record who reported the outcome and whether it was independently verified. A CUSTOMER_ASSERTED verification means exactly that — nobody checked it.
  • Keeping your counterparty list current. An agent can only pay who you have said it may pay.

Product limits

  • One live mandate per agent. Decisions resolve against the agent's most recently published, unrevoked mandate. Several concurrent mandates for one agent are not supported. One mandate can be granted to several agents (up to 20), and they share its budgets; the set is fixed on publish.

  • The Authority Record does not list the mandate's other agents. A record names the agent that acted, the mandate and its policy_hash. The agents sharing the mandate are held by mnd8t (GET /v1/mandates/{id}) and are not part of the signed record or the hash, so a third party cannot see from a record alone that its budget was shared.

  • A new mandate starts with a fresh budget. Mandates are not replaceable: to change an agent's authority you revoke its mandate and create a new one, and the new one's budgets start empty. Spend under the revoked mandate is not carried over, even within the same day or month. If the agent should not spend more today, give the new mandate lower limits. Publish the new mandate before revoking the old one if the agent must not be left without authority in between.

  • The mandate assistant drafts; it can be wrong. The AI assistant on the dashboard proposes terms from a conversation. It can misread an amount or pick a default you did not intend, so review every field in the form before creating the draft. It covers the form's fields only (not objectives, asset budgets or identity attestation rules), is available only where the deployment sets ANTHROPIC_API_KEY_FILE, and sends the conversation and your agent and counterparty names to Anthropic. It plays no part in decisions.

  • Budget windows are daily and monthly. Quarterly or arbitrary periods and per-counterparty budgets are not built.

  • Approved reservations expire after 24 hours. Confirm or cancel promptly; a decision left hanging releases its budget hold and must be re-authorised. The exception is a decision whose authorisation artifact was claimed: its budget is never released on a timer, because the executor may already have moved the money. It becomes UNRECONCILED and keeps counting against the limit until you report the outcome with /confirm or /fail. Nothing reconciles this automatically — mnd8t does not observe the transaction — so an executor that dies mid-flight leaves budget held until somebody says what happened.

  • Budget periods follow the mandate's schedule timezone (UTC when no schedule is set). Changing that timezone mid-period starts a new period.

  • Use with real funds is not supported. The terms prohibit it during the preview. This is a contractual limit, not a technical one: mnd8t has no execution path to switch off, and every account, network and confirmation it holds is as reported by you, so it cannot tell testnet spending from mainnet. See SECURITY.md for the review required to support real funds.

  • Environments are a label, not a partition. An API key is SANDBOX or LIVE_TEST, but data is not separated by environment: every key in an organisation sees the same agents, mandates, budgets and records, and all are signed with the same key. Use a separate organisation to keep test traffic apart.

  • Wallet support is limited to a simulated account and one EVM testnet adapter. Additional providers connect through the same adapter interface.

  • The AP2 adapter (v0.1, behind ENABLE_AP2_MAPPING) projects one approved decision, not a standing mandate. It produces single-use AP2 Open Payment Mandate content for one payment and refuses anything else. The constraints are payee, amount, checkout and expiry. A recurring AP2 mandate with a budget is not produced. AP2 verifiers would track that budget, not mnd8t, so two such mandates could each spend everything that remains. Other limits:

    • mnd8t does not sign, issue or verify AP2 credentials (SD-JWT, key binding), and has not been tested for AP2 conformance.
    • Fiat ISO 4217 currencies only.
    • AP2 execution dates are calendar dates, so the AP2-side bound is the artifact's expiry date. The mnd8t-side check accepts immediate payments only.
  • AP2 mandate input reads one AP2 version, and not all of it. A decision request may carry AP2 v0.2.0 Payment and Checkout Mandates, verified against keys the organisation registered. It is off unless the deployment sets ENABLE_AP2_INPUT. Limits:

    • One version: v0.2.0. Any other, including v0.1.0, is rejected.
    • ES256 keys only, found by kid among keys registered with mnd8t. No x5c certificate chains, DID resolution or JWKS: nothing is fetched.
    • Constraints that need state across payments (payment.budget, payment.agent_recurrence) or the merchant's line items (checkout.line_items) are not evaluated, so mandates carrying them are rejected (AP2_CONSTRAINT_UNSUPPORTED). The mnd8t mandate's own budgets still apply to every payment.
    • A merchant key must be bound to a registered counterparty, so a merchant mnd8t has never heard of cannot be paid through AP2 at all (AP2_SIGNER_UNKNOWN), not even into an escalation.
    • The Checkout JWT is checked for its signature, its hash and its merchant (for checkout.allowed_merchants). Its line items and totals are not read; the amount evaluated is the Payment Mandate's.
    • One decision per closed Payment Mandate, whatever the outcome: an agent rejected for budget must present a new mandate, not retry the old one.
    • aud and nonce on the closed mandate are set for the credential provider or merchant, so mnd8t does not check them.
    • A future execution_date is recorded but not acted on: the decision, and its budget, are for now.
    • Interoperability is tested against AP2's own reference SDK (fixtures it generated, and its verifier accepting mnd8t's test tokens), not against other AP2 implementations, and there is no AP2 conformance suite.
  • No enterprise SSO, billing, or mobile application.

  • Organisation membership is managed by an administrator. There is no self-service invitation flow; a user with several organisations acts on one at a time.

  • Approval emails need a provider. With EMAIL_PROVIDER=resend, each escalation emails its secure link to the organisation's admins and approvers. Without one, the link is in the decision response only; it is logged in development and never in production. The dashboard lists pending approvals either way. A failed send is logged and audited, not retried.

  • Outcome evidence is asserted by you, and nothing checks it. mnd8t does not fetch evidence from a carrier, merchant, bank or ERP, does not reconcile it against anything, and cannot tell a true delivery note from an invented one. GET /v1/mandates/{id}/outcome is only ever as good as what was submitted. There are no carrier, merchant or ERP integrations, no escrow, no refunds and no dispute management — an objective that comes back NOT_FULFILLED tells you so and does nothing about it.

  • An outcome needs an objective, and old mandates have none. Verification requires policy.objective on the mandate's published version. Mandates published before it existed return 409; adding one means replacing the mandate (a new mandate with an objective, published, and the old one revoked), because a published mandate is never amended.

  • Outcome evidence deduplicates only on a reference you supply. Two submissions of the same fact without a reference are two facts, and will be counted twice.

  • API keys created before scoping hold every scope. They were backfilled rather than downgraded, because the migration cannot tell an agent's key from an operator's and silently removing authority would break live integrations. GET /v1/api-keys flags them as scopes_backfilled. Rotate any that an agent carries to the AGENT preset — until you do, those keys can still publish a mandate.

Operational limits

  • PostgreSQL 16 or later. The schema uses a conservative baseline, so it will run on older majors for local development, but anything below 16 is unsupported and end-of-life majors must not be used in production.
  • Rate limiting is per instance. Multi-instance deployments should add a shared store or edge rate limiting to enforce a global budget.
  • One active signing key at a time. Rotation publishes a new key id; earlier keys stay verifiable when their public halves are listed in EVIDENCE_RETIRED_PUBLIC_KEYS. Leave one out and the records it signed can no longer be verified. Retired keys are configuration, not a managed key history.
  • Performance is not load-tested. Decision latency is well inside target in normal use, and the metrics endpoints compute on read — expect to add aggregation before high sustained volume.
6 min read · Need something that isn't here? Browse all documentation