Every execution has a proof you can check without trusting the API operator: the API’s audit events for it, in an append-only log whose checkpoints are signed by a notary inside the attested TEE. You check it against a log head that an independent witness, front-1, signed.
At a glance
  • Get it: GET /v1/agents/{agent_id}/operations/{correlation_id}/proof, or api.getOperationProof() in the SDK, for any op_… execution.
  • Check it: fetch a fresh head from the witness with the pinned witness key, request the proof from that head’s size, and pass the head to verifyOperationProof(proof, origin, trusted). The check itself runs offline.
  • Then, yourself: look up the settlement transactions on-chain, and verify the notary’s TDX quote as on TEE & Attestation.
How it works: the API records every action’s audit events in an append-only Merkle log. The log’s checkpoints are signed by a notary whose keys are bound to a hardware attestation of the code that runs it. The notary also reports every checkpoint to a witness on front-1, a separate host outside the VM, which keeps the log’s newest head and accepts only consistent extensions of it. The proof endpoint returns the retained events for one execution, with proofs anyone can check.

Pin the witness key

The witness signs the head it serves with an Ed25519 key. Pin this key in your own code or configuration. Never read it from an API response, because the API only relays the witness’s answer. The same key is WITNESS_PUBLIC_KEY in the compose that the attestation covers, so you can confirm it against app_compose from /tee/info.

Get and verify a proof

The call needs your partner API key. correlation_id is the op_… id of an execution of that agent. Owner intents (intent_…) have no operation proof. Verification needs a trusted checkpoint that does not come from the proof. The flow is:
  1. Fetch the witness head. fetchWitnessCheckpoint sends a fresh nonce to /tee/witness and checks front-1’s signature with the key you pinned.
  2. Request the proof with from_size set to that head’s size, so the response carries a consistency proof from your head.
  3. Pass the head to verifyOperationProof.
verifyOperationProof needs no network. It throws NoteError or ProofError when the proof is for another log, a signature is wrong, the checkpoint does not extend your trusted one, an event isn’t this execution’s, or a recorded result was changed after it was committed. Without a trusted checkpoint it refuses to verify at all. If the server’s log is behind the size you sent, the endpoint answers 409 transparency_checkpoint_behind. Fetch the head again and retry. The verify-operations example is a complete script.

Response

Each event has an action, a created_at time, a status, a proof and its evidence: evidence is the result the event recorded, as canonical JSON, or null when it recorded none. For an execution, it includes the settlement transaction hashes. notary holds log_key and notary_key (the verifier keys), signing_address, and birth: the TDX attestation quote, its report_data, and previous, the checkpoint the notary continued from after a restart, or null on its first boot. The log’s public tiles and latest checkpoint are served at https://log.agentsonintents.com/.

What a proof lets you check

A PROVEN event’s proof carries the event’s opening (the committed content, in the extra line), its leaf index, the inclusion path and the signed checkpoint. verifyOperationProof checks that:
  1. The notary keys belong to the origin you pinned and match the birth attestation’s report_data.
  2. The checkpoint is signed by the log key and cosigned by the notary key.
  3. The checkpoint extends the trusted checkpoint you passed in. A smaller tree, a fork of the same size or a missing consistency path is refused.
  4. The opening hashes to a leaf the checkpoint includes, and names this execution, its action and its time.
  5. The evidence hashes to the opening’s evidenceHash, so a result changed after it was committed is refused.
It returns the new checkpoint. Store it as your next trusted head only after the attestation check below passes. Keep trusted heads in your own storage, not anywhere the API operator controls. A saved head proves continuation from that head, not that it is the newest one, so fetch a fresh head from the witness each time you verify. Two more steps are yours to run:
  1. Check the settlement on-chain. Look up each NEAR transaction the evidence names: tx_hash, transaction_hash and settlement_tx_hash, and destination_tx_hash only when the withdrawal’s chain is near. Each should be final and successful. Confidential routes other than withdrawals, and same-chain withdrawals that settle by intent hash alone, name no public transaction, so there is nothing to look up for them.
  2. Check the attestation. Verify the TDX quote in notary.birth with a quote verifier, such as dstack-verifier, run by you or by a service you trust. TEE & Attestation shows how. Its report_data must equal verified.birthReportData. That ties the keys to the attested code.
Together, this shows that the attested code recorded the event under those terms, and that no recorded event was removed or rewritten afterwards. A proof does not replace the execution’s status, which reflects chain and provider evidence. It adds an audit record that the operator cannot quietly edit.

Receipts

A completed transfer, withdrawal, swap, limit order or deposit also has a receipt: a separate log leaf that commits only to the settled terms. It names no agent or account, so you can hand it to a payee, who verifies it against the same witnessed log without an API key.

Retention and errors

The API keeps audit events for 90 days. Their commitments stay in the log, so the tree stays valid, but an expired event no longer appears in proofs. See Status & Errors for every code.