VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

How Superintelligence Works | Agent JSON Merge Patch — Null Deletes, Array Replacement and Safe Preconditions

Three secondary students review textbooks and notes together at a classroom table.

JSON Merge Patch lets today’s AI agents request narrowly scoped changes to JSON resources, but its small payloads can conceal large effects. Under RFC 7396, omitted object properties stay unchanged, null deletes an object member, and any supplied array replaces the entire existing array. A safe agent previews the resulting document, checks permission and schema constraints, and uses HTTP version preconditions so a stale plan cannot silently overwrite somebody else’s newer work.

Did you know that a one-line patch can delete a field or replace a whole roster? The important skill is not merely producing valid JSON. It is predicting the exact transformed tree, identifying when a concurrent editor has changed the resource, and reading back the committed state before reporting completion. These are present-day software engineering techniques for tool-using agents; they do not assume that artificial superintelligence exists.

This guide develops the mechanism from the specification, works through original numerical examples with explicit units and denominators, contrasts JSON Merge Patch with JSON Patch and PUT, explains timeouts and recovery, and closes with transfer exercises and primary sources. The reader can use it to assess real API workflows without treating a successful network call as proof that every business effect happened.

Contents

Start with one object and one proposed change

JSON Merge Patch solves a narrow but useful engineering problem: describe changes to a JSON document by sending a small JSON value that resembles the desired portions of the resulting document. A client need not transmit every unaffected property. An absent object member means leave that member alone. A supplied non-null member normally becomes the new value, possibly after recursive merging when both sides are objects. A member explicitly supplied as null is a deletion instruction. These are document transformation rules, not assertions about the permissions of the requester.

Imagine an assistant adjusting the status of an assigned task. The stored resource contains a title, owner, deadline, audit metadata and labels. The assistant wants to change only the owner. Sending a full replacement document creates an unnecessary chance of erasing fields it never read. Sending a merge patch containing just the owner makes the intended update easier to inspect. But this smaller write does not remove the need to check whether another worker changed that owner while the assistant was thinking.

The implementation question is therefore two-part. First ask, “If the document has not changed, what exact JSON tree will this patch produce?” Then ask, “How will the server know whether the base document is still the one the client saw?” The first question belongs to RFC 7396. The second is addressed by HTTP preconditions and the surrounding application protocol. Neither question should be skipped merely because an agent generated the payload automatically.

The recursive merge rule in plain language

RFC 7396 describes a function applied to two inputs: the existing JSON target and a JSON patch. If the patch is an object, the algorithm treats a non-object target as an empty object. It then walks each patch member. When a patch member has JSON null, that key is removed from the target object if present. When it has any other value, the algorithm recursively applies the patch value to the existing member and stores the result. The processed target object is returned.

If the patch itself is not an object, it replaces the entire target. That second branch is easy to miss because most everyday examples use a top-level object. A top-level string patch, number patch, array patch, boolean patch or null patch has replacement semantics. A service may constrain its resource schema so that only objects are accepted, but that is an application validation rule rather than the general RFC 7396 transformation rule.

This recursive structure creates different outcomes for two superficially similar inputs. A patch of nested object shape can change one grandchild while retaining its siblings. A patch that supplies an array replaces that array as one complete value, regardless of how many objects sit inside the array. Once the team understands that the unit of recursion is an object member, not an arbitrary path into every JSON type, the rest of the failure modes become predictable. Before sending a write, compute its resulting tree on a private copy and compare it with the stated user intent.

Absent is not null, and null is not a stored null

Suppose a resource currently contains the three members name, nickname and notes. A patch that simply omits nickname makes no request concerning nickname. A patch that includes nickname with the value null requests removal of that member. This distinction is not optional; it is the format’s definition. It prevents a single JSON Merge Patch document from expressing every possible target state.

Consider an application in which “not provided” means unknown, but an explicit JSON null means that a person has no middle name. Under merge-patch processing, writing the null does not store the explicit null value. It removes the member. If the distinction between missing and null matters, this update format is a poor fit for that field. Choose a format with an explicit replace operation, design an alternate representation, or expose a dedicated domain-specific action with unambiguous semantics.

Serializers create a particularly subtle risk. A form library might generate an object containing every possible field, filling optional fields with null. An agent may interpret those nulls as harmless blanks and send the object as a patch. The server correctly interprets them as deletion instructions. The repair is to construct a deliberate field-by-field patch from the requested change, not serialize an entire form or model indiscriminately. Tests should inspect the wire payload, because the difference between an absent property and an explicit null can disappear in higher-level language abstractions.

Nested objects merge; adjacent fields survive

A nested object patch follows object keys recursively. If a stored task has a schedule object containing both a timezone and a due date, a patch containing only a new due date inside schedule retains the timezone. This behavior is often what makes merge patches attractive for configuration APIs: callers can be explicit about the exact branch they intend to change while leaving unrelated object members untouched.

The rule has an important qualification. If the stored schedule is a string rather than an object, and the incoming schedule value is an object, the algorithm treats the old string as an empty object and builds an object from the patch. A careless agent cannot assume that a mismatched type will always produce an error. The merge algorithm itself specifies a result; a schema validator must reject changes the application considers invalid. Type validation belongs around the merge operation.

Nested deletion also requires precise placement. Sending a null for the schedule member removes the entire schedule object. Sending an object whose dueDate member is null removes only that dueDate member while preserving any other schedule members. A reliable preview presents the path as “schedule.dueDate will be deleted” rather than merely displaying the word null. If a reviewer needs to approve a safety-critical change, the description should identify exact paths, original values and proposed outcomes, not only show raw JSON.

Why arrays are replaced instead of merged

Arrays are a boundary in JSON Merge Patch. An incoming array is a non-object value, so it replaces the corresponding target array as a whole. The system does not compare array elements by index, merge objects inside the array, or append a new entry automatically. For a short static list maintained by one editor, replacement may be entirely appropriate. For a shared roster, address list, queue or ordered checklist, it can become an accidental data-loss mechanism.

Imagine a list containing six task labels. An assistant reads all six, creates a revised seven-label array, then submits it. While the assistant is working, another editor adds an eighth label to the stored list. Without a version precondition, the assistant’s stale seven-label replacement can erase that eighth label. The overwritten fraction of the updated eight-label list is one of eight newly added elements, or 12.5 percent of that current list, in this illustrative scenario. This number is a calculation from invented inputs, not a measured incident rate.

Do not call an array replacement an append operation. If appending or selectively editing elements is the actual task, an endpoint with a domain-level add operation or a properly supported JSON Patch operation may be more suitable. If merge patch must be used, fetch the current array, obtain a usable strong ETag, compute the entire replacement array deliberately, send If-Match and handle a rejection by re-reading and resolving the conflict. A merge patch’s concise syntax cannot by itself protect unseen array entries.

Top-level scalars and objects that change type

A non-object patch replaces the entire target, even if the target is a complex object. For example, applying the JSON string “done” as the whole patch to a JSON object produces the string “done” as the resulting JSON value under the abstract algorithm. Similarly, applying the JSON array [1, 2] replaces the target with that array. This is different from supplying an object whose one member happens to be an array; in that case only the named member is replaced.

Conversely, applying an object patch to an existing scalar resets the effective target to an empty object before processing the patch members. A numeric value can therefore be replaced by a new object without the merge function itself protesting. Whether this is sensible for a task API, billing configuration or student-record service is an entirely separate question. A typed resource API should validate shape before accepting the write and after computing the proposed result.

This distinction matters when an agent automatically repairs malformed data. An agent that sees a wrong type might attempt a generic object patch and unintentionally discard information that should have been preserved for human review. A defensive workflow reads the type, checks the domain schema, refuses surprising type transitions without authorization, and records a before-and-after preview. Type surprises are signals to inspect the source of the data, not opportunities to “fix” the record silently. The safest transformation is not always the one the algorithm can technically compute.

PATCH is a method; merge patch is one document format

The HTTP PATCH method and the JSON Merge Patch media type answer different questions. PATCH says that a request supplies instructions for modifying a resource. The format of those instructions must still be known to the recipient. RFC 7396 registers application/merge-patch+json for merge-patch documents. RFC 6902 registers application/json-patch+json for a different instruction format. A body that is valid JSON is not automatically a supported merge patch.

An agent should consult the API contract and, where supplied, the server’s advertised accepted patch formats. RFC 5789 defines the Accept-Patch response header for advertising patch document media types. The presence of PATCH as an allowed method does not prove that every patch media type is supported. An endpoint may accept one, both or a different documented format. Do not guess based on the name of the method alone.

In a request, Content-Type identifies the representation being sent, so application/merge-patch+json should accompany a merge-patch body when the endpoint supports it. Accept is a separate request header about desired response representations; confusing these fields can create a request that looks plausible but does not communicate the patch format. When a server refuses an unsupported media type, the correct response is to inspect the API documentation and negotiate an actually supported format, not to resubmit the same semantics with an arbitrary generic JSON label. A failed request is a chance to correct the contract, not an invitation to change its meaning.

Why an ETag and If-Match matter more than a small payload

A small patch reduces the textual scope of a change, but it cannot guarantee that the original intent is still appropriate. HTTP offers conditional requests so a client can say, in effect, “apply this only if the selected representation still matches the version I read.” A GET response may provide a strong entity tag, commonly called an ETag. The subsequent PATCH request can include If-Match with that tag. RFC 9110 requires strong comparison for If-Match when entity tags are supplied.

This protection is particularly valuable in agent systems because reading, planning, requesting approval and writing may take several seconds or minutes. A tool-calling agent may have the right permission and still act on stale facts. A calendar appointment might have moved, an approver might have been reassigned, or a task could have been closed by another worker. The precondition makes the server perform the version check before a state-changing request, instead of trusting the agent’s memory.

A failed If-Match precondition is normally reported using 412 Precondition Failed, subject to HTTP’s documented nuances for requests that may already have been applied. The agent should interpret the failure as “my read might be stale,” not as a transient network timeout to retry unchanged forever. It must fetch the current representation, compare with the intent and either recompute a safe patch or escalate the conflict. If the server enforces a policy requiring a conditional request, it may use 428 Precondition Required; clients must follow the particular API’s documented behavior.

Worked task example: preserving fields a worker did not mention

The next three JSON examples show the initial representation, the requested merge patch, and the resulting representation. Notice that notes disappears rather than becoming an explicit null; unchanged labels and task status remain present. These objects illustrate the exact recursive rules rather than a live API response.

{
  "task": {
    "title": "Audit enrollment export",
    "owner": "agent-a",
    "status": "open"
  },
  "limits": {
    "hourlyCalls": 120,
    "retries": 3
  },
  "labels": [
    "review",
    "privacy"
  ],
  "notes": null
}
{
  "task": {
    "owner": "agent-b"
  },
  "limits": {
    "retries": 2
  },
  "notes": null
}
{
  "task": {
    "title": "Audit enrollment export",
    "owner": "agent-b",
    "status": "open"
  },
  "limits": {
    "hourlyCalls": 120,
    "retries": 2
  },
  "labels": [
    "review",
    "privacy"
  ]
}

Consider a fictional task resource with title “Audit enrollment export,” owner “agent-a,” status “open,” retry budget 3, a labels array containing “review” and “privacy,” and a notes property containing an explicit null. The agent is asked to assign ownership to agent-b and lower retries to 2. A suitable object patch has task.owner set to agent-b and limits.retries set to 2. It does not send the task title, status, labels or notes. Under the RFC’s object recursion, the resulting target retains all those omitted members.

Now add a second instruction: delete the notes field entirely. Because the stored notes value is null already, the distinction must be stated precisely. A notes:null member in the merge patch removes the member, so the resulting JSON does not contain a notes key at all. If the user actually wanted the notes property preserved as JSON null, the patch must omit it. Treating “clear notes” as a universal synonym for null would be a design mistake; some applications define clearing as deletion and others store null as a meaningful state.

The example contains two changed leaf values and one deleted top-level key. If a summary says “three fields changed,” that counts the changed owner, retries and removed notes once each; it does not count nested container objects as extra domain updates. A review interface should display the concrete differences so the person approving the action knows the scope. The fields and values here are illustrative, not records fetched from a production task service.

Worked array example: calculate the exact overwrite

Suppose a shared action list currently has four entries: check sources, review numbers, inspect permissions and publish a summary. A writing agent previously read the same first three entries before inspect permissions was added. It now sends a merge patch replacing actions with its old three entries plus archive the draft. That replacement also contains four entries, but inspect permissions disappears. Counting entries before and after alone gives four versus four and hides the loss.

The correct comparison uses set or sequence semantics appropriate to the application. Before the update, the current list has four actions. After the stale update, it has four actions. The intersection is three actions; one existing action vanished and one new action appeared. Thus one of the four actions in the latest pre-update list, or 25 percent, was lost in this deliberately constructed example. This is not a claim that 25 percent of real merges fail. It is a reminder that equal lengths do not prove semantic preservation.

With a strong precondition, the agent’s old version tag fails after the other worker’s update, so it must re-fetch. On the new read, the agent can propose five entries if the application allows both contributions: the original three, inspect permissions and archive the draft. If order matters, preserve the application’s ordering rule rather than relying on JavaScript object-key order or lexical sorting. If the two actions conflict, an automated union may itself be incorrect; human intent is the deciding factor.

A minute-by-minute concurrency race with exact outcomes

Imagine a resource version R7 observed by two agents at 10:00 local time. Worker One intends to change budget from 120 to 100 API calls per hour. Worker Two intends to replace an alerting array of two recipients with a three-recipient array. At 10:01, Worker Two commits its alert update and the resource becomes R8. At 10:02, Worker One submits a budget patch constructed from R7. The budget path and alerting path are distinct, but Worker One has not inspected the new R8 representation.

Without a precondition, a merge implementation usually preserves the alerting array because the budget patch omits it. Yet this observation should not be generalized into a promise of conflict safety. Business logic may couple limits to notifications; resource versions may contain server-computed fields; an authorization change might have happened since 10:00. A concurrent update can make a once-valid budget change invalid even when the modified JSON member names do not overlap.

If Worker One sends If-Match for R7, the server checks the selected representation and, because R8 is now current, rejects or otherwise resolves the failed precondition according to HTTP rules. Worker One fetches R8, verifies the recipient list and the updated alert policy, then asks whether 100 calls per hour still satisfies the task. The numbers have units: 120 and 100 are permitted API calls per hour, a change of 20 calls per hour, or 20 divided by 120 = 16.67 percent of the original allowance. A safe agent reports that specific change and its basis rather than claiming to have “reduced load safely” without evidence.

Retry logic after timeouts, duplicates and unknown results

An unknown write outcome is different from an explicit rejection. If a PATCH request times out, the server may have completed the change while the client lost the response. Sending a second unconditioned write without checking can interact badly with application side effects, last-modified versions or concurrent updates. Merge patch is often idempotent as a pure document transformation for the same target state and patch, but a real HTTP endpoint can trigger side effects such as audit events, notifications or derived calculations. The network outcome cannot be inferred from the client timeout.

A disciplined agent records the requested resource, old validator, exact patch bytes or parsed patch object, intended resulting paths and a request correlation identifier if the API supports one. After an unknown outcome, it GETs the resource and determines whether the intended state already holds. If the current version differs and the intended result cannot be proven, it stops the automated replay and reconciles. Do not create a second logical task merely because the transport failed.

If the API offers an idempotency key specifically for the operation, apply the contract defined by that API; RFC 7396 by itself does not define one. Reusing an opaque key safely depends on the server’s retention and duplicate-detection semantics. Always distinguish “the JSON result matches my target” from “every external effect occurred exactly once.” For example, seeing a new owner in a GET does not independently prove that a notification email was or was not sent. A reliable workflow tracks both resource state and the separate operational events that matter.

Distinguish transport success from business success

A 2xx HTTP response indicates a class of protocol-level success; it is not evidence that every downstream business goal succeeded. A server may accept a document patch and defer a workflow transition, or it may immediately validate and reject a forbidden state. The client needs the endpoint’s documented response contract. If a successful response includes an updated representation or a fresh ETag, compare it with the intended result. If the endpoint returns no representation, perform a follow-up read when independent verification is required.

Conversely, do not interpret every non-2xx response as proof that nothing happened. A timeout may hide a success; an intermediary may fail after origin processing; and an API might have partial downstream effects despite rejecting a larger business workflow. HTTP PATCH’s atomic application requirements address the resource’s patch application, not arbitrary external systems linked to that resource. Side effects require separate design and verification.

Suppose updating a review status should also queue an assignment notification. The status may read correctly while the notification service is delayed. The safe report says that the resource update has been confirmed and that notification delivery has not. It does not convert a single successful read into a claim that both operations finished. The more external systems an agent touches, the more important it becomes to distinguish resource state, operational side effects and user-visible outcomes. Treat these as separate assertions with separate evidence.

Merge computation is not business validation

JSON Merge Patch defines a transformation of JSON data items, not a schema checker. A patch may replace a numeric budget with a string, remove a required identifier, insert an unexpected attribute, or turn a structured object into a scalar. The merge algorithm does not automatically know that a curriculum level must be an integer, that a date must follow a permitted format, or that one value must be smaller than another.

For safety, the server should validate the proposed final resource against its type rules and business invariants. Validation should take place before committing the update, using the actual current resource selected under the precondition. Some APIs also restrict which paths callers may modify. Clients can run local validation to catch errors earlier, but client-side checks do not replace server-side enforcement. An agent is a caller, not an authority to waive rules.

Imagine an hourly call allowance that must lie between 10 and 200 inclusive. A patch proposing 210 is structurally valid JSON and valid merge-patch syntax, yet invalid under that declared domain rule. The server should refuse it rather than clamp it silently unless clamping is part of the documented contract. Silent coercions make agent verification difficult because the requested and committed states diverge. A helpful error tells the caller which field failed and why without exposing sensitive internal data. The agent can then adjust its proposal only if the user’s goal permits the new value.

Least privilege: deleting a key is still an action

An agent may be authorized to change task descriptions but not approval status, spending limits or access-control fields. Since merge patches can include arbitrary object keys unless constrained, the server should enforce field-level authorization based on the authenticated identity and context. A global “can edit this resource” permission may be too broad for workflows that separate drafting, approval and payment. Null deletion instructions deserve the same authorization scrutiny as ordinary replacements.

Consider a resource with role, approvedBy and payoutAccount members. An untrusted agent asked to edit a description might submit a patch containing approvedBy:null, whether through a compromised prompt or a faulty serializer. The correct defense is not a sentence in the agent’s prompt saying “never delete approvals.” The server must refuse unauthorized paths and enforce business invariants. Treat the payload as untrusted input even when it originated from an internal model.

Before building a patch, an agent can make its own allowlist of fields justified by the user’s request. This narrows the chance of accidents, but it is defense in depth, not enforcement. The service must also authenticate the caller, scope access to the correct tenant or project, check each changed field, and avoid leaking more information in errors than necessary. Concurrency controls and authorization solve different problems: If-Match protects against stale versions; it does not establish that the caller is permitted to perform the change.

Make deletions visible in approval screens

Deletion is where compact merge patches are most prone to misreading. In a review interface, a null value can look like a missing form value, a deliberate empty answer or a request to remove stored data. The approval presentation should translate the patch into consequences: “Remove notes,” “Remove schedule.dueDate,” or “Remove notifications.recipients,” with the old values summarized when safe to display. For an array, show the entire before-and-after list or a meaningful element diff.

When a user asks an assistant to “clear the queue,” clarify internally whether the domain operation means set an array to empty, delete the array member altogether, or mark each queued item completed. Under merge-patch semantics those are three different operations. Empty array means replace the member with []; null means delete the member; updating each element requires another operation or format. An agent should not collapse three meanings into the same raw payload.

For irreversible or consequential changes, request a human approval step through the application’s workflow. The agent may prepare a preview and gather context, but the approval should cover exact paths and effects. If the resource has changed after approval, a version precondition must trigger another review when the intent is no longer the same. Approval for a patch built against R7 is not a universal permission to apply a different patch to R9. Clear semantic previews protect the user from format-specific surprises.

How Merge Patch differs from JSON Patch

Despite similar names, JSON Merge Patch and JSON Patch are separate standardized representations. Merge Patch resembles an object fragment and has recursive object merge semantics, null deletion and complete replacement of arrays. JSON Patch, defined in RFC 6902, is an ordered array of operations such as add, remove, replace, move, copy and test. It identifies locations using JSON Pointer paths. The format determines whether a null is treated as a value or an instruction.

If you need to set a property to literal JSON null, the JSON Patch replace or add operation can express that state without using null as a deletion marker. If you need to insert one item into an array at a particular index, JSON Patch has array path semantics that Merge Patch lacks. If you need to describe simple modifications to a predominantly object-shaped configuration, Merge Patch may be easier to read and less verbose. Neither format can replace schema validation, authorization, or resource-version checks by itself.

One particularly important distinction concerns concurrency. JSON Patch has a test operation that can assert a value at a path in the same patch sequence. Merge Patch has no analogous embedded test instruction. For whole-resource optimistic concurrency, an HTTP If-Match precondition is useful with either format when the server supports validators properly. Choosing the right document syntax makes an update expressive; combining it with correct HTTP and domain constraints makes it safer in a shared system.

When a full PUT is more honest than a patch

Sometimes the user really intends to replace a resource’s complete state. A configuration export imported into a newly provisioned environment, for example, may be a declarative full replacement rather than a list of selective updates. In those cases, a documented PUT operation can be clearer: the client submits the desired representation as a whole, subject to the server’s schema and conditional update rules. Using Merge Patch to approximate complete replacement can obscure whether old omitted fields should survive.

The choice should follow domain intent, not simply payload size. If the user says “set the exact list of permitted reviewers to these three people,” a full reviewer-list replacement might be appropriate. If the user says “add one reviewer without changing anyone else,” that same replacement is dangerous unless the list was freshly read, concurrency was protected and the union operation has correct semantics. A PATCH is not automatically safer than PUT because it is shorter.

A sound API documentation page explains whether PUT replaces all writable fields, which server-managed fields remain untouched, and which conditional headers are supported. For PATCH it names the accepted patch media types and fields. Clients should not infer all these behaviors from HTTP verbs alone. Read the resource contract. For critical workflows, compare the resulting representation with the intended state and retain a record of why a full replacement or a partial update was chosen.

A practical agent planning checklist without hidden magic

Before constructing the request, identify the user’s actual instruction in domain language. “Change the project lead” is a different request from “transfer the entire project ownership and permissions.” Look up the resource through an authenticated API with the correct tenant and scope. Record its current version, status and the fields relevant to the change. Determine whether the action is allowed; do not let the patch format become a shortcut around application permissions.

Next, construct a minimal merge patch containing only the intentionally modified object members. Explicitly review every null as a deletion instruction and every array as an entire replacement. Compute a local proposed result and run schema checks if available. A useful diff shows added paths, replaced paths, deleted paths and complete array replacements. If the proposed result is not exactly what the task requires, revise before any network write.

Finally, send the documented Content-Type and a resource precondition when supported. Distinguish a definitive validation or permission refusal from a stale-version response and from an unknown transport outcome. Read back the saved state from the authoritative source, verify the specific paths and record any unverified side effects separately. For changes with a human approval requirement, include approval before commitment, and re-evaluate it if the resource has materially changed. These steps are engineering practices for today’s software agents; none assumes that artificial superintelligence currently exists.

A batch of updates is not one magical transaction

An agent often wants to patch several resources during one task: update a ticket, revise a checklist and write a summary. Three HTTP PATCH requests are still three separate operations unless the application explicitly offers an atomic multi-resource transaction. A successful first patch does not guarantee the second will succeed, and a failed third does not automatically roll back the first two. Merge Patch describes changes to an individual JSON target, not distributed commit across services.

Consider a fictional workflow with five documents, each carrying its own strong ETag. Four updates succeed and the fifth is rejected because its version changed. The confirmed success fraction is four successful document updates divided by five attempted document updates, or 80 percent; that arithmetic does not imply that 80 percent of the overall business objective is safely achieved. The business task may require all five to be consistent before any external action is allowed. The correct next step depends on the application’s transaction boundaries and reconciliation rules.

A robust agent tracks a per-resource ledger: target ID, intended fields, precondition, response, observed result and next action. If partial completion is unacceptable, use a service-side transaction or well-defined compensating workflow rather than attempting ad hoc reverse patches. Reversing a merge patch is not always possible from the patch alone, especially when null deletes values or array replacements destroy the earlier list. Save authorized prior state when recovery requires it and protect it as sensitive data.

What should appear in logs and change history

Operational observability helps teams diagnose errors without exaggerating certainty. Useful records include the resource identifier, request or job correlation ID, authenticated principal, patch format, a redacted summary of changed JSON paths, base validator, response status and independent readback result. Avoid dumping entire resources or secret values into broad logs. A patch can contain access tokens, personal data or protected notes even when it looks like ordinary JSON.

Track classes of outcome separately: accepted with verified state, explicitly rejected on version conflict, rejected on authorization or schema grounds, and unknown because of network interruption. A single aggregate “success rate” can hide the operational difference. For instance, 90 accepted writes out of 100 attempts equals 90 percent transport acceptance, but if only 60 underwent independent readback the verified-write denominator is 60, not 100. The resulting reported figure must say precisely what it measures.

For recurring automation, count retried attempts separately from unique logical modifications. A single intended change could produce three transport attempts without representing three different user requests. Monitoring should also flag repeated null deletions or whole-array replacements in sensitive resources for human review. Those patterns are not automatically malicious, but they can indicate an incorrect serializer or ambiguous task interpretation. The aim is to establish a reliable causal record, not to fill dashboards with impressive but poorly defined percentages.

Threats at the parsing, policy and transport boundaries

A merge-patch endpoint exposes several trust boundaries. The HTTP layer must authenticate requests and apply transport security. The parser must process bounded input safely and reject malformed documents. The application must authorize each relevant field, validate the resulting object and enforce concurrency checks. The storage layer must commit the agreed representation without unexpected partial transformation. No single layer can safely assume that another layer performed all checks.

RFC 7396 notes that features of the textual JSON representation need not survive processing. Whitespace, member ordering and number precision beyond the implementation’s capacity are not part of the merge-patch guarantee. Duplicate object member names are particularly problematic because the standard does not define a result for objects that allow duplicate names. A defensive service should define strict parsing behavior, reject ambiguous input where appropriate, and avoid using string-level equality as proof that two parsed JSON trees have identical meaning.

Protect against resource exhaustion as well. A highly nested patch or very large array replacement can be expensive to parse, validate and store. Applications should apply appropriate size, depth and rate limits and maintain audit trails suitable for their sensitivity. These are general service-design controls, not new guarantees made by RFC 7396. For high-risk actions, no agent instruction should substitute for server-enforced authorization, transaction integrity and independent verification.

Worked policy example: three checks before one edit

A fictional school’s internal scheduling service stores each lesson as a JSON object. A tutor assistant may change the room, but only a coordinator may cancel a lesson or remove its teacher assignment. Suppose the resource has room “B2,” teacher “T4” and status “confirmed,” and the tutor requests room “B3.” The intended patch is a single room replacement. The local diff must say B2 to B3. It must not contain status:null or teacher:null merely because those form fields were blank.

There are three different checks. First, field authorization: is the authenticated tutor permitted to edit room? Second, domain validation: does B3 exist and permit the class size, accessibility and time required? Third, state concurrency: is the confirmed lesson representation still the one the assistant read? Passing one check does not imply passing the others. For example, a coordinator might have cancelled the lesson in the meantime, so the room change should not proceed automatically on stale assumptions.

If the timetable has 18 seats and there are 16 students registered, the spare capacity is two seats, calculated as 18 seats minus 16 students assuming one seat per student. The occupancy fraction is 16 divided by 18, or approximately 88.9 percent. These explicit units and assumptions turn vague “room is big enough” claims into checkable statements. Capacity still does not prove suitability: accessibility, equipment and local policies may impose further conditions. These are illustrative quantities, not live eduKate class enrollment facts.

Transfer test: switch from task status to a shared student roster

Here is a changed-context problem. A scheduling agent reads a roster with students A, B, C and D and an ETag for version 11. It intends to remove student C on an authorized request, so it prepares a merge patch replacing the roster array with [A, B, D]. While it is composing the request, an administrator adds student E and the resource becomes version 12. The question is: what should the agent send next, and what would an unsafe replay lose?

The answer is not “send the old three-student array again.” A stale unconditional replacement would remove C as intended but would also erase E, because the array is replaced as a whole. The old roster has four members, the current roster has five, and the stale proposed result has three. Two students in the current roster would be absent after the unsafe replay: C intentionally and E unintentionally. The agent should use If-Match with the version-11 validator, expect a mismatch once version 12 exists, then re-fetch and re-evaluate the change.

After confirming C should still be removed and E should remain, the new proposed roster is [A, B, D, E], four students. This example tests transfer of the rule from a task’s label array to a student roster where privacy and access controls matter much more. Do not infer that simply reading a roster authorizes publishing its names; this demonstration uses letters in place of personal information. Human review remains appropriate for consequential enrollment changes.

The minimum test matrix for an API client or server

Tests should cover the semantics of absent members, null deletions, nested object updates, replacement of an array, replacement of a scalar, and non-object top-level patches. Use exact expected output trees rather than relying only on HTTP status codes. Include a target with a field already missing: a null deletion for that field should leave it absent, not introduce a new null. Include an existing member with explicit null and a patch that omits it: it should remain explicit null.

Add concurrency tests using two clients that read the same ETag. Let one update the resource and verify that the other’s outdated If-Match does not silently overwrite changes. Test the format-negotiation boundary by sending the wrong Content-Type to an endpoint that accepts only merge patch. Test authorization by attempting to delete a protected field with null. Test a resulting document that violates a schema constraint even though its patch is syntactically valid.

Finally simulate uncertain network outcomes, ensuring the client reads by resource ID before replaying a mutation. Check that arrays of length zero, arrays containing null, nested keys with empty strings and large but permitted numbers are handled according to the contract. When a test fails, diagnose whether the error is in RFC-level transformation, HTTP preconditions, domain validation, permissions or the recovery workflow. Those layers may produce similar symptoms but require different repairs. A test suite is useful only when its assertions map to the actual system contract.

Common mistakes and precise repairs

One mistake is saying “Merge Patch edits any JSON path.” It does not offer JSON Pointer path operations and cannot alter one array entry without replacing the array. The repair is to use a deliberate whole-array replacement with concurrency protection or switch to an endpoint designed for an element-level update. Another mistake is saying “null sets the value to null.” In an object merge patch, null deletes that member. The repair is to omit the member when its existing explicit null should survive or use a format that can store the desired null.

A third mistake is treating a successful HTTP request as proof that the broader workflow completed. The repair is an independent resource readback and separate verification of any expected external effect. A fourth is blindly retrying a timed-out mutation; the repair is reconciliation before replay. A fifth is assuming that a smaller payload eliminates stale-read risk. The repair is version checking, conflict resolution and clear approval boundaries.

A sixth mistake is mixing up field permissions with version checks. If-Match does not grant authorization. An authenticated editor cannot safely modify every nested member merely because their ETag is current. A seventh is assuming the server has to preserve exact textual JSON formatting after a patch; the RFC describes data-level operations, not text editing. Finally, an agent should not describe these standard engineering patterns as proof of an existing artificial superintelligence. They are practical controls for present-day distributed software and tool-using AI agents.

Frequently asked questions

Can JSON Merge Patch append to an array? Not by itself. A supplied array replaces the corresponding array value. To append while preserving concurrent contributions, use a supported element-level operation, or fetch and conditionally replace the complete array after examining the latest state. Is sending an empty object a no-op? For an object target it makes no member changes; for a non-object target the recursive algorithm first treats the target as an empty object and returns that object, so it is not universally a no-op.

Can a merge patch store a literal JSON null? Not through a null-valued member of an object patch, because that means delete. The right alternative depends on the API’s schema and supported update formats. Does a PATCH response always contain the new object? No. The response representation and status depend on the API contract; a verified follow-up read may be necessary. Can two agents patch different keys safely without a version check? Some independent changes will not collide at the JSON key level, but domain invariants, derived fields and simultaneous decisions can still make an unchecked update unsafe.

Is it safe to retry exactly the same merge patch? The pure transformation is often idempotent against the same state, but request side effects, validators and intervening concurrent writes mean blind network replay is not generally safe. Does If-Match replace authentication? No; concurrency and authorization are separate controls. Is JSON Merge Patch the same as JSON Patch? No; they have different media types and semantics. Which rule should a student remember first? Absent means leave unchanged, null in an object patch means delete, and arrays are replaced whole.

Related reading and a practical learning pathway

To understand the broader operation of modern AI agents, begin with the How Super Intelligence Works learning hub. It organizes present-day engineering mechanisms without presenting hypothetical superintelligence as an achieved capability. Readers who need element-level JSON operations can continue with Agent JSON Patch: pointer escapes, atomic edits and safe preconditions, a separate topic with a different update format.

Readers maintaining HTTP clients may also benefit from Agent HTTP 421 Misdirected Requests, which addresses origin authority and connection reuse rather than resource-level document merging. These articles are related through engineering reliability, not interchangeable. Choose the one matching your problem: document transformation, explicit path operations or connection routing.

A productive practical exercise is to take three fictional objects and write a before-and-after table for each proposed merge patch. Then add a concurrent editor and a strong version validator to every scenario. Mark the point at which the agent must stop and re-read rather than proceed. Finally ask what evidence proves the saved resource matches the user’s actual goal. Someone who can answer those questions understands the mechanism more deeply than someone who merely memorizes the syntax of a PATCH request.

Primary standards and source-backed distinctions

The definition of the merge algorithm, application/merge-patch+json media type, array replacement behavior, null deletion behavior, treatment of non-object patches and interoperability test cases come from RFC 7396, JSON Merge Patch: https://www.rfc-editor.org/rfc/rfc7396.html. Read section 2 and Appendix A for the clearest formal treatment; it is the authority for the transformation described throughout this article.

The meaning of HTTP PATCH, error handling and the Accept-Patch advertising mechanism comes from RFC 5789, PATCH Method for HTTP: https://www.rfc-editor.org/rfc/rfc5789.html. The strong comparison behavior of If-Match and the conditional-request processing model are defined in RFC 9110, HTTP Semantics: https://www.rfc-editor.org/rfc/rfc9110.html. The distinction between the two JSON patch document formats is supported by RFC 6902, JavaScript Object Notation (JSON) Patch: https://www.rfc-editor.org/rfc/rfc6902.html.

The concrete task, roster, allowance and classroom examples in this article are constructed teaching cases with explicitly stated quantities, not claims about a deployed system. Recommendations concerning field-level authorization, human approval, observability and recovery are practical design conclusions derived from the protocol behavior; no RFC cited here certifies that any particular agent or vendor implements those recommendations correctly. Standards define interoperable rules, while the safety of a deployment depends on enforcement, testing and independent verification.

Discover more from eduKate Singapore

Subscribe now to keep reading and get access to the full archive.

Continue reading