Mutations
Mutations modify tool call parameters before they’re sent upstream. The agent never sees the modification — it believes its original parameters were used. This is useful for enforcing defaults, stripping fields, and overriding values.
How mutations work
Section titled “How mutations work”Mutations run after constraints pass but before the provider executes. They operate on a cloned copy of the parameters (via structuredClone) to prevent aliasing bugs.
create_event: allow: true mutations: - field: attendees action: delete - field: visibility action: set value: "private"In this example, even if the agent sends attendees and a visibility setting, the upstream call will have no attendees and visibility: "private".
Mutation actions
Section titled “Mutation actions”Set the field to a given value. If the field doesn’t exist, it’s created.
mutations: - field: visibility action: set value: "private"Supports any YAML value type — strings, numbers, booleans, arrays, objects:
mutations: - field: maxResults action: set value: 10 - field: replyAll action: set value: false - field: attendees action: set value: []Clamp a numeric field to a maximum value. If the agent provides a value above the cap, it’s reduced. If the value is at or below the cap, it’s left unchanged. If the field is absent or not a number, the mutation does nothing — the provider’s code default applies.
mutations: - field: maxResults action: cap value: 50This lets the agent control the value within bounds — requesting fewer results to save context, or more when it needs to scan a larger inbox.
delete
Section titled “delete”Remove the field entirely from the parameters.
mutations: - field: attendees action: delete - field: cc action: delete - field: bcc action: deleteNested fields
Section titled “Nested fields”Mutations support dot-notation for nested fields:
mutations: - field: start.timeZone action: set value: "America/New_York" - field: end.timeZone action: set value: "America/New_York"Execution order
Section titled “Execution order”Mutations are applied in the order they’re listed. This matters when one mutation depends on another:
mutations: # First: strip all attendees - field: attendees action: delete # Then: set visibility (order doesn't matter here, but listed for clarity) - field: visibility action: set value: "default"Constraints + mutations
Section titled “Constraints + mutations”Constraints are evaluated before mutations. This means constraints check the original parameters, not the mutated ones. The pipeline is:
- Constraints — validate original params → reject if any fail
- Mutations — modify cloned params
- Field policy — strip disallowed fields
- Execute — forward mutated params to provider
Examples
Section titled “Examples”Strip attendees from calendar events
Section titled “Strip attendees from calendar events”Prevent the agent from inviting people:
create_event: allow: true mutations: - field: attendees action: delete - field: guestsCanModify action: delete - field: guestsCanInviteOthers action: deleteForce private visibility
Section titled “Force private visibility”create_event: allow: true mutations: - field: visibility action: set value: "private"Cap search results
Section titled “Cap search results”search: allow: true mutations: - field: maxResults action: cap value: 50Strip CC/BCC from drafts
Section titled “Strip CC/BCC from drafts”create_draft: allow: true mutations: - field: cc action: delete - field: bcc action: deleteForce single reply (no reply-all)
Section titled “Force single reply (no reply-all)”reply: allow: true mutations: - field: replyAll action: set value: false