Mandates

Replace a mandate's capabilities/label/standing/expiry

Changed on

Optimistic concurrency: version is required and must match, or the update is refused. strategy (a proposal still waiting for the person: "Allow and edit") may carry only targets, budget (null removes it), review_every, explore, goal_kind and pace (bets, guardrails and cost_terms are not editable); the goal and plan stay as filed, the whole strategy is validated again (422 invalid_strategy, or strategy_not_editable once decided). TUNING A RUNNING PLAN (0.235.0): on an ACTIVE strategy mandate the grantor may send strategy: {explore?, goal_kind?, pace?} with no new approval (explore 0.05..0.5, goal_kind and pace from GET /api/v1/strategies/limits); these only tune effort and promise nothing. Any other key in strategy refuses the whole request, 422 strategy_not_editable ("only explore, goal_kind, pace can be changed while the plan runs"); a paused, revoked or expired mandate is refused as before. A value that already holds changes nothing: no version bump, no event. A real change bumps version, records one plain sentence per key in strategy.tunings ([{at, text}], newest 20, e.g. "You changed pace to careful."), tells the open sessions of the grantor and the agent on the mandates live topic ({kind, status, version}), and delivers the strategy_tuned event to the grantee agent only (never the person's bell): the mandate JSON (as in GET /mandates/{id}, so id, grantor, grantee, status, strategy, chat) plus type: "strategy_tuned", changes: {key: new_value}, strategy_id and version. The agent adopts the new values on its next plan sync. The term is expires_at. THE AGENT TUNES ITS OWN PLAN (0.243.0): the GRANTEE of a running strategy mandate sends {version, strategy: {explore?, goal_kind?, pace?}} with the same ranges and NO approval, and tells the person afterwards: the version bumps, each key is recorded in strategy.tunings as {id, at, by: "agent", key, from, to, text}, the person gets a quiet Activity row (strategy_tuned_by_agent: "<agent> changed pace to careful.") and the plan page offers Undo (POST /mandates/{id}/tunings/{tid}/undo). An agent grantor hears strategy_tuned with by: "agent", before: {key: old} and tuning_id. The agent can change NOTHING else here: locks, label, capabilities, standing, expires_at, days are 403 (locks_grantor_only, grantor_only), and any strategy key beyond the three is 422 strategy_not_editable; budgets, model_budget, targets, the term and capabilities widen only through the person (a proposal or a tune request). At most 10 tuning calls a day per plan (429 too_many_today). A key the person locked is 422 plan_locked ("You asked to keep this plan as is.", locked: [...]): file a tune request instead. KEEP THIS PLAN AS IS (0.243.0, the grantor only): locks: ["pace", "explore", "goal_kind"] or ["all"] locks those keys against the agent ([] lifts it); served on the mandate as locks; the grantor can still change them; unchanged locks bump nothing; 422 invalid_locks. Needs version like any update.

patch/api/v1/mandates/{id}

Request

  • Base URL: https://saltapp.ai
  • URL: https://saltapp.ai/api/v1/mandates/{id}
  • Auth: API key in header api-key

Path parameters

idstring required

Request body

labelstring
standingboolean
expires_atstring
daysinteger

0.240.0, a strategy waiting for the person: how long the plan lasts, from now (also read from inside strategy). With expires_at, 422 invalid_term in plain words ("The plan can last at most 90 days.", "Days it lasts must be a whole number from 1 to 90.", "The plan can't end in the past.", "The day it ends isn't a date."). A refused strategy edit is one plain sentence in error (the validator list stays in errors).

strategyobject

Edit a waiting strategy (targets, budget, model_budget, review_every, explore, goal_kind, pace), or tune a running one (explore, goal_kind, pace only; the grantor or, unless locked, the grantee agent).

locksstring[]

0.243.0, grantor only: keep this plan as is. [] lifts it.

versioninteger required

Response

OK

idstring uuid required
kind'explicit' | 'governance' | 'connection' required
status'proposed' | 'active' | 'paused' | 'revoked' | 'expired' | 'withdrawn' required

withdrawn (0.240.0): an unanswered proposal that a newer plan for the same goal replaced; nothing was granted. withdrawn_reason says why.

labelstring nullable
starts_atstring date-time nullable
expires_atstring date-time nullable
standingboolean
grantee_fingerprintstring nullable
key_changedboolean
parent_idstring nullable
depthinteger
versioninteger required
chat_idstring nullable
reasonstring nullable

The asking agent's own words (at most 1000 characters). Data, never Salt's sentence.

estimated_costobject nullable

A budget ask: {amount (decimal string), currency, period (daily|weekly|monthly)?, chain?}.

approved_by'self' | 'null' nullable

0.236.0: self when a ROOT agent approved its own plan (grantor == grantee, no card); null otherwise.

first_check_in_atstring date-time nullable

0.244.0: when the plan's first check-in lands, stamped on Allow from the review cadence (the moment of Allow plus hourly 1 h, daily 1 d, weekdays 1 d skipping Saturday and Sunday in the person's time zone, weekly 7 d, monthly 30 d). Null before Allow and on a plan with no strategy.

locksstring[]

0.243.0, "Keep this plan as is": the keys of a running plan the grantor locked against the agent's own tuning (all locks every tunable key). Set by the grantor with PATCH locks. Empty when nothing is locked.

plan_idstring nullable

0.240.0: the plan this grant was asked for (set with plan_id on the proposal); stopping or expiring the plan ends the grant too.

approve_firstobject[]

0.240.0: for each public-post / public-room / first-message row of this grant, {capability, mode, approved, needed}: the asks the person has approved so far and how many it takes (3) before the agent may ask to be told instead of asked.

withdrawn_reasonstring nullable

0.240.0: "Replaced by a newer plan" when status is withdrawn, else null.

resume_tokenstring nullable

Opaque (at most 200 characters), supplied by the asking agent and echoed on every mandate event so it resumes the exact parked step.

client_idstring nullable
client_namestring nullable
proposed_by_idstring nullable
accepted_atstring date-time nullable
paused_atstring date-time nullable
pause_reasonstring nullable
revoked_atstring date-time nullable
revoke_reasonstring nullable
childrenobject[]
trailobject

Changes

    • info

      added the optional property to the response with the status

    • info

      added the optional property ///// to the response with the status

    • breaking

      added to the response body oneOf list for the response status

    • breaking

      the response's body type changed from object to no type for status

    • breaking

      removed the required property from the response with the status

    • info

      added the new optional request property

    • info

      added the non-success response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status