# `get_goal`

Reads one goal: its wording, versions, audience, and search state.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

## When to use it

- Before any write, to get the current `scopeVersion` and `contextRevisionId`.
- To see which groups a goal is shared with, and whether it's hidden from any.
- To follow a search: `matching.run` shows its status and progress.
- To read a fellow member's goal shared with one of your groups, using its ID from [`get_group_details`](/docs/mcp/tools/get_group_details).

## Inputs

| Input | Required | Type | Description |
| --- | --- | --- | --- |
| `goalId` | yes | string | Goal UUID from [`list_goals`](/docs/mcp/tools/list_goals), [`get_group_details`](/docs/mcp/tools/get_group_details), or an earlier result |

## Returns

`{ "workspace": ... }`:

| Field | Type | Description |
| --- | --- | --- |
| `goal` | object | The goal, with the [`list_goals`](/docs/mcp/tools/list_goals) fields. On someone else's goal, `additionalContext` is empty and `clarificationQuestion` is null. |
| `isOwner` | boolean | You own this goal |
| `selectedGroups` | list | `{ publicId, name, hidden }` for each selected group you belong to. `hidden` is only ever true for the owner. |
| `availableGroups` | list | Owner only: every group the goal could be shared with |
| `matching` | object | Owner only: `run`, the current saved search state. On someone else's goal, `run` is null. |
| `searchQueued` | boolean | Owner only: Gravity will search this goal on its own shortly. Don't start a search while it's true. |

`matching.run` describes the search for the goal's current version. It's `null` if the goal changed and hasn't been searched since.

| Field | Description |
| --- | --- |
| `runId` | Search ID |
| `status` | `running`, `complete`, `failed`, or, rarely, `cancelled` |
| `stage` | `planning`, `searching`, or null |
| `searchProgress` | While running: `estimatedPercent` (at most 99), `completedNetworks`, and `totalNetworks`. Otherwise null. |
| `coverage` | `searchedMemberCount` and `groupMemberCount` |
| `eligibleMembers` | Members whose networks are new or updated since the last search. A `new-members` search covers them. |
| `failedMembers` | Members whose networks couldn't be searched last time. A `failed-networks` search retries them. |
| `fitPeopleCount` | How many people the search found |
| `error` | "The introduction search could not be completed." when the search failed, otherwise null |
| `startedAt`, `completedAt`, `updatedAt` | ISO 8601 timestamps |
| `goalScopeVersion`, `goalContextRevisionId` | The goal version this search covered |

This response deliberately excludes UI workspace fields and match payloads. Use [`get_goal_matches`](/docs/mcp/tools/get_goal_matches) to read saved matches through the requester-safe projection.

A missing or inaccessible goal returns the common `unavailable` error. Malformed IDs fail input validation before the application runs. You can read your own ended goal by its ID. Someone else's ended goal is readable only if you already have a conversation about it.

## Example

```json get_goal
{
  "goalId": "00000000-0000-4000-a000-000000000001"
}
```

Result (synthetic data):

```json result:get_goal
{
  "workspace": {
    "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,
      "contextRevisionId": "00000000-0000-4000-a000-000000000002",
      "scopeVersion": 2,
      "suggestedByGravity": false,
      "retiredAt": null,
      "createdAt": "2026-10-09T00:00:00.000Z",
      "isOwner": true,
      "version": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    },
    "isOwner": true,
    "selectedGroups": [
      {
        "publicId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "name": "Synthetic founders",
        "hidden": true
      }
    ],
    "availableGroups": [
      {
        "publicId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "name": "Synthetic founders",
        "description": null,
        "memberCount": 2,
        "hasActiveGoal": true,
        "isModerator": false
      }
    ],
    "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"
      }
    },
    "searchQueued": false
  }
}
```

## Related

- [`save_goal`](/docs/mcp/tools/save_goal) supports optional preconditions: `goal.version` checks all editable state, including visibility; scope/context versions check matching inputs.
- [Matches and searches](/docs/mcp/concepts/matches) explains search statuses.
