Step 4 of 8 Intermediate 18 min

Writing Safely: Create, Update & the 'Block, Don't Delete' Pattern

Lesson 4 — The moment your agent can write, the stakes change completely. Here's the exact pattern that keeps write actions safe — including the SAP-specific gotcha that trips up almost everyone building their first CRUD agent.

S
s4ready.ai Team

Prerequisites

  • Lesson 3: Your first MCP tool

The moment your agent can write, the risk profile changes instantly. A read-only agent that misbehaves gives a wrong answer. A write-capable agent that misbehaves creates a real record someone now has to notice, explain, and clean up.

Three write actions, three distinct traps

Three write actions, three distinct trapsCreate needs BusinessPartnerCategory and BusinessPartnerGrouping, both mandatory. Update needs a fetch-first sequence so the SDK captures the ETag before patching. Delete is not supported at all for Business Partner — the correct pattern is to set BusinessPartnerIsBlocked to true instead.CREATECategory + Groupingare silently mandatoryMiss it → a runtime errorthat looks unrelatedUPDATEFetch first, so the SDKcaptures the ETag —then PATCHSkip it → a 403 thatlooks like a permission bugDELETENot supported.At all. Ever.Set IsBlocked = trueinstead — audit stays intact
Every trap here is invisible until it fires — build the pattern in from the start, not after the first error.

Create: the field that trips up almost everyone

const builder = businessPartnerApi.entityBuilder()
  .businessPartnerCategory(category)   // 1=Person, 2=Org, 3=Group — required
  .businessPartnerGrouping(grouping);  // required — determines the number range

BusinessPartnerGrouping determines the number range for the new record. Miss it, and you don’t get a helpful validation message — you get an error that reads like it came from somewhere else entirely.

Update: fetch first, always

const bp = await businessPartnerApi.requestBuilder().getByKey(id).execute(dest);
bp.organizationBpName1 = newName;
await businessPartnerApi.requestBuilder().update(bp).execute(dest); // SDK sends If-Match automatically

PATCH needs a CSRF token and the current ETag, every time. The SDK handles both — but only if you .getByKey() first, so it captures the ETag before you .update(). Skip that sequence, and you’ll get a 403 that has nothing obviously to do with permissions.

Delete: not a workaround, the actual pattern

API_BUSINESS_PARTNER cannot physically delete a Business Partner — ever, by design, because a BP carries audit-relevant transaction history. The correct pattern is the workaround:

const bp = await businessPartnerApi.requestBuilder().getByKey(id).execute(dest);
bp.businessPartnerIsBlocked = true;
await businessPartnerApi.requestBuilder().update(bp).execute(dest);

Design your agent’s instructions around this from day one“you cannot delete a Business Partner; block it instead” — rather than discovering it live, when the model confidently tries to call a delete_bp tool that was never going to exist.

Try it yourself

Take your Lesson 2 write action. Write out its CSRF/ETag handling, and check whether your target API even supports a true delete — or has its own “block, don’t delete” hiding in its docs. Most SAP master-data and transactional APIs do. Assume yours does until proven otherwise.

Where this shows up in SAP

Every line above is real code from the Business Partner CRUD tutorial. Building Sales Orders instead? That tutorial shows the same discipline on header-plus-line-item creates — where the constraint differs: sales orders can be deleted, but only before a delivery or billing document exists.

Key takeaways

  • Create almost always has a silently-mandatory field — find it in the docs, not in a runtime error.
  • Update needs fetch-first so the SDK captures the ETag — skip it, and a missing header masquerades as an auth failure.
  • “Block, don’t delete” is frequently how the API actually works, not a design choice. Bake it into the instructions from day one.

Next: your tools work locally. Time to deploy the server somewhere an agent can actually reach it.