Skip to main content

Treeship for Claude Commerce Agents

Signed, offline-verifiable receipts for every tool call in anthropics/commerce-agents, on all three of its runtimes.

The reference draws its own boundary in docs/safety.md: the approval surface, payment, and log hygiene are "what a deployment owns". This package is what a deployment adds for the record of what happened. It records; it does not gate. The reference's provenance gates, caps, and host approval still decide what runs.

What it does

commerce_common.execution.BaseToolExecutor.execute is the one method every tool call passes through on the Messages API, the Agent SDK, and Managed Agents. TreeshipExecutorMixin overrides it:

  1. a signed intent receipt before dispatch: tool, SHA-256 of the canonical arguments, session tag;
  2. the tool, exactly as the reference runs it;
  3. a signed result receipt: status (ok, blocked with the gate's name, error), SHA-256 of the result text, event types, timing.

Each receipt names its parent, so a session reads intent → result → intent → result … from the Treeship session's root, and treeship verify walks it as one chain. A held call is a signed refusal, not a missing receipt.

Never written: the arguments, the result text (fenced third-party content on the reference), or the commerce session id (the request credential). The receipt carries the same twelve-hex session tag the reference's own log lines use, so an operator holding the id can correlate and a reader cannot.

Install

git clone https://github.com/anthropics/commerce-agents && cd commerce-agents
python3.11 -m venv .venv && source .venv/bin/activate   # the reference needs Python 3.11+
pip install -r requirements.txt            # their seven packages (unregistered on PyPI)
pip install treeship-sdk treeship-commerce
curl -fsSL https://treeship.dev/install | sh   # the CLI does the signing; the demos also fetch it themselves
treeship init --config .treeship/config.json   # a workspace for this directory

Or let Claude Code wire it

claude plugin marketplace add zerkerlabs/treeship
claude plugin install treeship-commerce@treeship
/add-treeship-receipts merchant      # or shopping, or both

The plugin (plugin/) mirrors the reference's commerce-builder: one command that reads your project and wires the seams below on your runtime, and one skill on what the receipts carry.

Use

from treeship_sdk import Treeship
from treeship_commerce import TreeshipReceipts, attach, receipted
from treeship_commerce.lifecycle import close_session, start_session
from shopping_agent.executor import ShoppingToolExecutor

ts = Treeship()
root = start_session(ts, name="storefront:acme", actor="agent://shopping")

executor = receipted(ShoppingToolExecutor)(backend=..., config=..., skills=..., session=..., state=..., memory=...)
attach(executor, TreeshipReceipts(ts, actor="agent://shopping", session_id=session.session_id, parent_id=root))

# ... the runtime calls executor.execute(...) as it always did ...

close_session(ts, summary="...")          # seals a .treeship package; `treeship session report` publishes it

All three runtimes construct executors themselves through executor_class (ShoppingAgent, ShoppingToolset, the MCP server's build_server). Give receipted() a recorder factory and each executor gets its own recorder on its first tool call:

ReceiptedShopping = receipted(ShoppingToolExecutor, recorder=lambda ex: TreeshipReceipts(
    ts, actor="agent://shopping", session_id=ex._session.session_id, parent_id=root))

Same for MerchantToolExecutor.

Recording never breaks the agent path: a receipt that cannot be written warns once, is counted in TreeshipReceipts.dropped, and later results say intent_recorded: false where the intent is missing. Nothing is invented. TREESHIP_DISABLE=1 turns recording off.

Demo

TREESHIP_BIN=... python -m treeship_commerce.demo

Runs the reference's shopping executor over the retail mock with no model and no API key: a search, a product read, an add, an add the provenance gate holds, a checkout hand-off. Prints every receipt id, seals the session, and shows the treeship verify command.

TREESHIP_BIN=... python -m treeship_commerce.demo_merchant

The merchant side: a staged price change, held while unapproved, applied once under a signed single-use operator approval, then refused on replay while the reference's own in-process approval mark is still set. Prints the grant id and the journal's record of its one use.

Checkout

receipted_backend(backend) wraps a storefront backend so checkout_handoff also signs a hand-off receipt: cart digest, item count, subtotal, currency, and a digest of each hosted URL (never the URL). order_placed(receipts, order_ref=..., amount=..., currency=...) is the host's half: a signed order receipt on the chain after the hand-off, naming it, the order reference digested. A holder of the checkout card can recompute the cart digest from the card alone.

Approvals

MerchantApprovals turns the host's y/N into a signed Approval Grant scoped to one actor, one action, and one change (change://<change_id>), max_uses=1. approved(receipted( MerchantToolExecutor), approvals) signs the apply's intent receipt with the grant's nonce, so the CLI reserves a use in the Approval Use Journal before signing. A second apply finds the grant spent; a grant for another change is refused by scope. The receipt says approval: "proven" or "unproven" with the reason. Recording only, unless enforce=True. Needs treeship-sdk 0.29.0 or later (attest_action takes subject).

On the Agent SDK runtime, approving(toolset, approvals) wraps MerchantToolset.host_approve and host_clear in place, so the reference console's y/N loop mints and forgets grants with no edits. On the Messages API the host calls approvals.grant() beside its own mark. On Managed Agents the platform's prompt is the approval surface and the click is outside the process; an apply there is receipted with no approval claim, never an invented one.

Verifiable Intent at hand-off

Verifiable Intent is the Mastercard-maintained v0.1 draft for proving an agent was authorized to buy. treeship vi attest signs its Layer 3 pair with the spec's agent_attestation claim pointing at this receipt chain. Run it at hand-off and the chain head it names is the hand-off receipt, so the credential binds the cart that went to checkout:

from treeship_commerce import attest_at_handoff, vi_verify

summary = attest_at_handoff(
    ts, receipts,
    mandate=l2_sdjwt,                 # the user's Layer 2, from their wallet
    checkout_jwt=merchant_jwt,        # the merchant's checkout token
    merchant="merchant-uuid-1", items=[("BAB86345", 1)],
    amount_minor=27999, currency="USD",
    aud_network="https://www.mastercard.com", aud_merchant="https://tennis-warehouse.com",
    out="./vi-out",
)
summary["attestation"]["chain_head"] == receipts.last_handoff   # True
vi_verify(ts, mandate=l2_sdjwt, out="./vi-out")["outcome"]      # "pass"

The purchase values you pass must describe the cart: the check against the mandate happens before anything is signed, and a purchase outside it raises with nothing written. The attestation is itself a receipt (vi.l3.attested) on the chain after the hand-off, and the host's order chains onto it. Needs treeship 0.31.

Keep the preimages

Receipts carry digests only. To settle a dispute you also need the originals: the arguments and result keyed to the receipt's artifact_id, the cart that went to checkout, the order reference. Keep them in your own store under your own retention rules; Treeship deliberately does not. args_digest, text_digest and cart_digest recompute the digests from the originals, and then a receipt proves this ran, not something with the same hash.

What this does not do (yet)

  • Prove the work is correct. A receipt is evidence of what ran and what the gates decided. It does not make a wrong answer right.

Tests

TREESHIP_BIN=/path/to/treeship python -m pytest
ANTHROPIC_API_KEY=... TREESHIP_BIN=/path/to/treeship python -m pytest tests/test_live.py   # one real turn

Thirty-five cases on a real isolated ship over the real retail and merchant mocks: chain order and linkage, a held call signed as blocked with its gate, digests-only content, recording failure leaving the tool untouched, TREESHIP_DISABLE, attach refusing an executor that would record nothing, one per runtime, and the approval properties: a grant binds to its receipt, is spendable once, is refused for another change, enforce=True holds an unapproved apply, the receipt note is the CLI's reason rather than the SDK's wrapper, the merchant side on all three runtimes through executor_class, and arguments that arrive as parsed pydantic models (the MCP server's shape) digesting like their dicts, and the checkout hand-off: the cart digest recomputable from the card, the URL never written, the host's order chaining from the hand-off, and an unwrapped backend's order saying so.

Release files for treeship-commerce 0.31.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for treeship-commerce 0.31.5
File Size Uploaded
treeship_commerce-0.31.5.tar.gz 46.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for treeship-commerce 0.31.5
File Interpreter ABI Platform
treeship_commerce-0.31.5-py3-none-any.whl Python 3 none any Details

Total release size: 81.9 kB

Release files / treeship_commerce-0.31.5.tar.gz

Download URL treeship_commerce-0.31.5.tar.gz
Size 46.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e02cccff33545ac782051bac01c67ba416d5b7e237ffc475818030328dfe5a3a
BLAKE2b-256 checksum
How to use checksums
7537f064697b426973965c5e56a410f872d8d1d2b65f0df746dadac511e10f89
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / treeship_commerce-0.31.5-py3-none-any.whl

Download URL treeship_commerce-0.31.5-py3-none-any.whl
Size 35.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
68e0279eb55951219ac9e581a18d9aa3b58e2c70b56d5fb001d63d2c66523f7f
BLAKE2b-256 checksum
How to use checksums
42298af128b25e63369e7a3508c5e2ebaefb62cf64bd7640064a2c40cff77d43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.31.9

2 release files

0.31.8

2 release files

0.31.7

2 release files

0.31.6

2 release files

This release

0.31.5 This release

2 release files

0.31.4

2 release files

0.31.3

2 release files

0.31.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page