Bounded agent tools
Define the smallest order change an agent may submit
Build a delivery-note tool by separating generated input, business validation and the durable write. Each layer answers a different question.
In this article
Write the contract in business terms
The tool accepts an order identifier and delivery note. It does not accept arbitrary field names, a customer identifier or a status override. This makes the intended effect obvious before any model integration exists.
Define length and character-handling rules according to the destination system. Preserve useful punctuation and line breaks where supported, but reject oversized input and unexpected fields. Treat the note as data throughout rendering and storage.
The order identifier still needs an access check. A correctly shaped identifier can point to another customer's order, and an eligible order can become ineligible between proposal and execution.
Load and validate trusted state
Resolve the caller from the server session, load the order and confirm that the caller may add notes to it. Check the business state, such as whether dispatch has already begun. Return a specific rejection when the requested change is no longer allowed.
{
"operationId": "op-example-104",
"orderId": "order-example-88",
"expectedVersion": 7,
"deliveryNote": "Use the loading entrance on the east side."
}The example includes a version so the executor can detect a stale proposal. The operation identifier should be created or scoped by the trusted application. It is not a substitute for caller authentication or object access checks.
Commit with a concurrency rule
If the order lives in the application's database, use the chosen transaction or conditional-update mechanism to ensure the state checked is the state being changed. If another service owns the order, use its supported version or conditional-write contract.
When the version has changed, do not silently apply the note to a different situation. Reload the order and decide whether the proposal needs regeneration or user review. The appropriate rule depends on whether the intervening change affects the delivery instruction.
Record the operation result with the changed order version. Repeated requests for the same operation should return that result or a pending status according to the idempotency contract. Reject reuse of the identifier with a different note rather than treating it as the same request.
Return enough information to explain the effect
The result should identify the order, operation status and committed version. Avoid returning unrelated customer fields merely because the downstream API included them. A small result reduces accidental disclosure and keeps the assistant's explanation focused.
Test the operation without a model first: permitted note, unauthorised order, stale version, duplicate request and conflicting reuse of the operation identifier. Then connect generation and verify that malformed proposals are rejected through the same path. The tool's correctness should remain testable even if the model is replaced.
Primary sources
PostgreSQL: explicit lockingAWS Builders' Library: idempotent APIsReferences checked 11 September 2026.