CLAUDE LABJP
SECURITY — Claude Security, which scans a connected GitHub repository and returns CWE-tagged findings with a suggested patch, now runs on the latest Mythos generation. It is in public beta for Enterprise plansDESIGN — The reasoning behind it is worth noting: a capable model is riskiest with direct access, and constraining output to a fixed shape such as a patch or an alert lowers that risk considerablyCOMMERCE — Anthropic published blueprints for commerce agents. Shopper-facing agents suggest and add to cart; merchant-facing agents advise on inventory and pricing. Neither completes the purchaseCLI — Claude Code v2.1.256 fixes launch failures on macOS 12 Monterey, along with errors in remote and scheduled sessionsAUTO — v2.1.257 adds a Containment Escape rule to auto mode, guarding against unauthorized cloud credential use and cross-tenant operations. If you live in auto mode, it is worth checking what now stopsLIMITS — The 50% weekly limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promo baseline, and this applies only to Claude Code weekly limitsSECURITY — Claude Security, which scans a connected GitHub repository and returns CWE-tagged findings with a suggested patch, now runs on the latest Mythos generation. It is in public beta for Enterprise plansDESIGN — The reasoning behind it is worth noting: a capable model is riskiest with direct access, and constraining output to a fixed shape such as a patch or an alert lowers that risk considerablyCOMMERCE — Anthropic published blueprints for commerce agents. Shopper-facing agents suggest and add to cart; merchant-facing agents advise on inventory and pricing. Neither completes the purchaseCLI — Claude Code v2.1.256 fixes launch failures on macOS 12 Monterey, along with errors in remote and scheduled sessionsAUTO — v2.1.257 adds a Containment Escape rule to auto mode, guarding against unauthorized cloud credential use and cross-tenant operations. If you live in auto mode, it is worth checking what now stopsLIMITS — The 50% weekly limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promo baseline, and this applies only to Claude Code weekly limits
Articles/API & SDK
API & SDK/2026-09-03Beginner

Don't Hand Your Agent the Tool That Commits — Sorting Tools Into Advise, Prepare, and Commit

Before you wrap irreversible actions in an approval gate, decide which ones never belong in the tool list at all. A three-tier inventory, a rewritten tool definition, and a small script that flags commits hiding in your schema.

tool-use24agent14commercedesign4

I was writing out the steps for a store price change as a tool one evening, and I stopped right after typing the name apply_price_change. The input schema was already there. All that remained was adding it to the tools array. Once I did, Claude would call it the moment it decided the change was needed.

As an indie developer I ship a handful of apps, and I've always touched pricing and release settings by hand in the store console. The procedure itself is short — maybe a dozen lines if you write it out — and that shortness is exactly what makes it tempting to turn into a tool. What stopped me wasn't difficulty. It was the mismatch between how easy the call would be and how much work undoing it would take.

On September 2nd, Anthropic published blueprints for commerce agents: reference implementations for retail, travel, telecom, and ticketing, split into a buyer-facing shopping agent and a merchant-facing agent for store operators. What caught my eye wasn't the feature list. It was that the shopping agent stops at handing a completed cart to checkout. Completing the payment isn't counted among the agent's possessions.

Decide What You Won't Hand Over, Before You Add Approvals

The usual answer for irreversible actions is an approval gate: the tool gets called, execution pauses, a human looks at it and lets it through. I use gates too, and there are places that genuinely need them.

But a gate is a mechanism that stops things after they're called. It assumes the stopping side is working. When the notification doesn't arrive, when the hold expires, when a branch in the gate logic was never written — what happens next depends on which way the default falls. If it falls toward execution, the accident looks exactly the way it would have without the gate.

A tool that isn't in the list, on the other hand, can't be called at all. That single property — not depending on the health of the stopping mechanism — has done more for my sleep than any amount of gate logic.

There's a second thing I like about leaving the name out. A gate has to be re-read every time the tool set changes, because the branch that protects a call is written somewhere other than the call itself. An absent tool needs no maintenance. Nothing about next month's refactor can quietly reconnect it.

If undoing it requires a human decision, its name doesn't go in the tool list. I place that line before I think about gates at all. Gates are for fine-grained control over what's left inside the line.

The gate mechanics themselves — pausing and resuming, asynchronous notifications, expiry handling — are covered in Inserting Approval Gates Into Your Agents. What I want to work through here is the step before that.

Three Tiers: Advise, Prepare, Commit

For a while I sorted tools into two buckets: reads and writes. That didn't work well. A single "writes" bucket ends up holding both saving a draft and pushing to production. Both are writes. One of them can be erased, and the other can't.

Three tiers hold up better.

TierWhat the agent ownsShape of the return valueExamples
AdviseLook up, compare, recommendCandidates, comparisonsCatalog search, inventory checks, pricing suggestions
PrepareAssemble, draftA draft with an id and a statusCart assembly, reply drafts, a pending price change
CommitNot handed overPayment, sending, publishing, deleting, refunding

Mapping the two blueprint agents onto these tiers makes the pattern easy to see. The shopping agent advises through search and comparison, prepares by assembling a cart, and then hands off to checkout. The merchant agent answers questions about sales performance, flags inventory problems, recommends pricing and promotions, and drafts campaigns. Neither of them steps into the third tier.

When a borderline case comes up, I ask myself one question: to undo this, would I need someone other than me? A refund request, retracting an email that already went out, rolling back a price that's already live — none of those close with my hands alone. What doesn't close is tier three.

Reversibility also depends on where an action lands, not just what it's named. The same delete can be recoverable in one place and permanent in another. I wrote up how I measure that in The Same rm -rf Was Recoverable in Ten Places and Unrecoverable in Five.

Rewriting the Definition So Commit Becomes a Draft

The inventory shows up as a change to the tool definition. Here's what I had started writing that evening.

# Before: the outside world changes the moment this is called
tools = [
    {
        "name": "apply_price_change",
        "description": "Change the store price of the given SKU to a new price.",
        "input_schema": {
            "type": "object",
            "properties": {
                "sku": {"type": "string"},
                "price_jpy": {"type": "integer"},
            },
            "required": ["sku", "price_jpy"],
        },
    }
]

And here's what it became. The name changed, the description changed, and — most importantly — the character of the return value changed.

# After: calling it only changes a review queue
tools = [
    {
        "name": "draft_price_change",
        "description": (
            "Create a draft price change and queue it for review. "
            "Does not change the store price. A human applies it separately."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "sku": {"type": "string"},
                "price_jpy": {"type": "integer"},
                "reason": {"type": "string", "description": "Why this price"},
            },
            "required": ["sku", "price_jpy", "reason"],
        },
    }
]

The handler returns a draft without touching anything outside.

import uuid
 
PENDING = []  # a database or a queue in production
 
def draft_price_change(sku: str, price_jpy: int, reason: str) -> dict:
    current = load_current_price(sku)          # read only
    draft = {
        "draft_id": str(uuid.uuid4()),
        "status": "awaiting_review",
        "sku": sku,
        "from_jpy": current,
        "to_jpy": price_jpy,
        "reason": reason,
    }
    PENDING.append(draft)
    return draft

I made reason required for my own sake, later. When I open the review queue in the morning, a column of price deltas tells me nothing I can act on. One line explaining why the number is what it is makes approving or rejecting a much shorter decision.

The point of the rewrite is that the return value carries only a draft_id and a status. From the model's side, all that comes back is the fact that a draft now exists. The store price stays where it was until I open another screen and apply it myself.

Check the Return Value, Not the Tool Name

Once you have more than a handful of tools, definitions start drifting between tiers without anyone noticing. You can catch them by reading, but I wanted a machine to look too. This script just picks out hard-to-undo verbs from names and descriptions.

# tool_commit_lint.py — look for commits hiding in the tool list
import json
import re
import sys
 
COMMIT_VERBS = ["place", "submit", "charge", "capture", "refund",
                "cancel", "publish", "send", "delete", "deploy", "transfer", "apply"]
DRAFT_MARKERS = ["draft", "proposal", "preview", "plan", "quote", "candidate"]
 
def lint(tools):
    findings = []
    for t in tools:
        text = f"{t.get('name','')} {t.get('description','')}".lower()
        hit = [v for v in COMMIT_VERBS if re.search(rf"\b{v}\w*", text)]
        drafty = any(m in text for m in DRAFT_MARKERS)
        if hit and not drafty:
            findings.append((t.get("name", ""), hit))
    return findings
 
if __name__ == "__main__":
    tools = json.load(open(sys.argv[1], encoding="utf-8"))
    found = lint(tools)
    for name, verbs in found:
        print(f"COMMIT? {name}  <- {', '.join(verbs)}")
    print(f"{len(found)} / {len(tools)} tools need a second look")
    sys.exit(1 if found else 0)

Running it over six definitions on my machine gave this.

COMMIT? place_order  <- place, charge
COMMIT? apply_price_change  <- apply
COMMIT? send_review_reply  <- send
3 / 6 tools need a second look

build_cart passed because its description says preview, and draft_price_change passed too. send_review_reply got flagged, which is what I wanted: once a reply to a store review goes out, it goes out.

I wouldn't take much comfort from a pass, though. Verb choices vary from person to person, and a calm-sounding update_status can finalize a payment without a single suspicious word in its name. The script is a set of markers, not a net.

What I do trust is the pass rate over time. When a run that used to report zero starts reporting one, something changed in the last few commits, and I'd rather read a small diff today than reconstruct a week of them after an order goes out on its own.

The last check is the return value. If what comes back is a draft id and a status, you're in tier two. If it's a report of something that already happened — an order number, a delivery confirmation, a published URL — you're in tier three. Names can be rewritten. Return values don't lie.

What You Can Do Tomorrow Morning

Open one tools array, read the definitions from the top, and say out loud whether each return value describes something about to happen or something that already has. I keep the three tiers on a sticky note at the edge of my screen, and I still put a finger on it every time I add a tool.

Not handing over irreversible actions is less about caution than about being able to explain yourself afterward. The range of what we hand to agents will keep widening — I'm sure of that. What I'd rather protect is the habit of counting what stops being undoable before I widen it.

Thank you for reading. If even one entry in your own list turns out to be worth a second look, this was worth writing.

Reference: Building Commerce Agents with Claude

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API & SDK2026-07-09
Same Output, Different Path — Guarding Agent Trajectories with Invariants
When the default model changes, your final output can stay correct while the path your agent takes quietly shifts. Here is a trajectory regression harness built on recorded tool traces and deterministic invariants, with working code and measured numbers.
API & SDK2026-06-29
When Context Editing Made My Agent Re-run the Same Search — Field Notes on Clear Boundaries and Cache Invalidation
After turning on Context Editing to auto-clear tool results, the agent forgot what it had just read, re-ran the same tool, and the cache rebuilt every turn so costs went up. Field notes on instrumenting the silent regression and setting trigger, keep, and clear_at_least from measured data.
API & SDK2026-05-05
Building a 'Think-and-Search' AI Agent — Claude API Extended Thinking × Tool Use
A deep dive into combining Claude API Extended Thinking and Tool Use. Covers frequent errors, a complete research agent implementation in Python, plus cost estimation, timeout design, and error recovery for production use.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →