Browse docssave_goal
save_goal
Creates, patches, or ends a goal you own. Saving starts no search.
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: true · openWorldHint: false
When to use it#
Only when asked to create, edit, share, hide, or end a goal. Resolve its exact identity and explain the audience for sharing changes. Explain that ending archives its introduction chats.
An edit supplies only the fields the member wants changed. Omitted fields stay unchanged. New authorized edits can update current state without a mandatory prior read. Use an optional version precondition when the change should depend on a particular state.
Inputs#
| Input | Required | Type | Description |
|---|---|---|---|
goalId | yes | string or null | null to create; otherwise the exact owned goal ID. |
text | no | string | Required and nonblank for creation, up to 2,000 characters. Omit on edits to preserve wording. Only a literal empty string ends a goal; whitespace-only wording is rejected. |
selectedGroupPublicIds | no | list of strings | Complete replacement audience when supplied, up to 100. Omit on edits to preserve it; new goals default to private. [] makes it private. |
hiddenGroupPublicIds | no | list of strings | Complete replacement list of selected groups to hide the goal from. Omit to preserve kept groups' settings; added groups start shown. |
additionalContext | no | string | Complete replacement private details, up to 4,000 characters. Omit to preserve them; "" clears them. |
expectedVersion | no | string | Opaque goal.version from get_goal. Constrains an edit to that complete state, including visibility. |
expectedScopeVersion | no | integer or null | Optional matching-input precondition from goal.scopeVersion; omit or use null for creation. |
expectedContextRevisionId | no | string | Optional context precondition from goal.contextRevisionId. |
requestId | yes | string | New UUID per action. Keep the same ID and arguments for a retry. |
Keep confidential details in additionalContext, outside shared text. Goals for a fixed beneficiary remain private and their beneficiary cannot change. See Goals and audiences.
What each change does#
- Wording, private context, and audience changes save immediately and cancel this goal's obsolete search. Other goals' searches continue.
- Visibility-only changes save immediately without changing matching inputs or stopping a search.
- Saving starts no replacement search. Call
start_goal_matchingseparately for an authorized search. - Ending archives the goal's introduction chats and cancels its search. It cannot be reopened. End with just
text: ""rather than combining ending with other edits.
All supplied fields commit together. Validation, access, version, and request-ID failures leave them unchanged. Obsolete workers cannot publish further results as current after the edit commits. Existing conversations remain attached to the goal.
Returns and retries#
Success returns status, outcome, message, goalId, scopeVersion, matchingRunId, cancelledMatchingRunIds, and currentState. MCP saves always return matchingRunId: null; an existing search can still appear in currentState.matching.run.
| Outcome | Meaning |
|---|---|
saved | The requested changes were committed. |
no_change | All supplied changes already match current state; the goal was unchanged and no search started. |
ended | The goal was ended and its chats archived. |
currentState contains the owned goal, selected groups, and current search state using the same safe projections as get_goal. It is an observed snapshot, not a promise that other actors cannot change the goal afterward.
Retries compare every supplied field. Identical current state returns no_change, even when a supplied version is old. If this request was already applied and the desired fields now differ, return version_conflict and current state without reapplying it. A supplied stale version also rejects a new edit that would change state. Different arguments under an already-used request ID return request_id_conflict. No historical outcome is replayed.
Errors use the common contract. For a conflict, explain that the goal changed since the edit was prepared, inspect currentState, and prepare a new action only within the member's intent.
Examples#
Create a private goal:
{
"goalId": null,
"text": "Find design partners",
"additionalContext": "Synthetic private details",
"requestId": "00000000-0000-4000-a000-000000000002"
}
Change only wording:
{
"goalId": "00000000-0000-4000-a000-000000000001",
"text": "Find design partners",
"requestId": "00000000-0000-4000-a000-000000000002"
}
Example response for an existing goal (synthetic data):
{
"status": "success",
"outcome": "saved",
"message": "Goal saved.",
"goalId": "00000000-0000-4000-a000-000000000001",
"scopeVersion": 2,
"matchingRunId": null,
"cancelledMatchingRunIds": [],
"currentState": {
"goal": {
"id": "00000000-0000-4000-a000-000000000001",
"memberId": "00000000-0000-4000-a000-000000000003",
"beneficiary": null,
"ownerName": "Synthetic member",
"ownerImageUrl": null,
"text": "Find design partners",
"additionalContext": "Synthetic private details",
"clarificationQuestion": null,
"version": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"contextRevisionId": "00000000-0000-4000-a000-000000000002",
"scopeVersion": 2,
"suggestedByGravity": false,
"retiredAt": null,
"createdAt": "2026-10-09T00:00:00.000Z",
"isOwner": true
},
"selectedGroups": [
{
"publicId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"name": "Synthetic founders",
"hidden": true
}
],
"matching": {
"run": {
"runId": "00000000-0000-4000-a000-000000000002",
"goalId": "00000000-0000-4000-a000-000000000001",
"goalScopeVersion": 2,
"goalContextRevisionId": "00000000-0000-4000-a000-000000000002",
"status": "running",
"stage": "searching",
"activities": [
"researching"
],
"searchProgress": {
"estimatedPercent": 50,
"completedNetworks": 1,
"totalNetworks": 2,
"completedTurns": 3
},
"fitPeopleCount": 1,
"hasReviewedMatches": false,
"completedAt": null,
"error": null,
"eligibleMembers": [
{
"displayName": "Synthetic member",
"isCurrentMember": true,
"reason": "updated"
}
],
"failedMembers": [],
"coverage": {
"searchedMemberCount": 1,
"groupMemberCount": 2
},
"startedAt": "2026-10-09T00:00:00.000Z",
"updatedAt": "2026-10-09T00:01:00.000Z"
}
}
}
}