> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clawdot.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# errand_search_addresses

> MCP tool errand_search_addresses — find addresses by keyword or by the user's current location, and surface saved addresses that match

## errand\_search\_addresses

Finds addresses and returns two result sets at once: `candidates`, the places found by the search, and `saved_matches`, addresses the user has already saved that match this search. The same place name can have multiple matches — never auto-pick the first one, let the user choose. Addresses in `saved_matches` already have their door number and contact phone filled in, so the user can place an order right away without repeating that information.

<Note>
  **Address flow**: once you find a candidate place, save it with `errand_save_address`. An address that already appears in `saved_matches` is already saved — skip saving and use its `id` directly as `address_id`.
</Note>

### Two ways to search — supply at least one

* **The user named a place** ("send it to People's Square") → pass `keyword`, optionally with `city` to narrow it down.
* **The user said "from where I am right now"** → there is no place name to search on; pass their `lat` / `lng`. You get back the names this location belongs to, from specific to broad (e.g. "星洲花园南区圣陶沙韵", "星洲花园南区", "星洲花园"), so the user can confirm which one is right.
* **Both supplied** → the search runs on `keyword`, and the coordinates only rank nearby results first.

<Warning>
  When the user names a place, **do not let the coordinates override `keyword`** — otherwise "send it to People's Square" turns into a search for where they are standing.
</Warning>

### Parameters

| Parameter          | Type   | Required | Default | Description                                                                                                                                 |
| ------------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `consent_grant_id` | string | Yes      | —       | User consent grant ID (`cg_` prefix), from `errand_verify_user_bind`                                                                        |
| `keyword`          | string | No       | —       | Place / address keyword, e.g. "西湖文化广场". Supply this or `lat`/`lng`; omitting both returns `KEYWORD_REQUIRED`                                |
| `city`             | string | No       | —       | City name to narrow the search (e.g. "杭州")                                                                                                  |
| `lat`              | number | No       | —       | Latitude of the user's current location (GCJ-02). On its own it searches by location; together with `keyword` it ranks nearby results first |
| `lng`              | number | No       | —       | Longitude (GCJ-02). Must be supplied together with `lat`; either one alone counts as no location                                            |

### Returns

```json theme={null}
{
  "candidates": [
    { "name": "五一广场", "address": "黄兴中路88号", "lat": 28.1965, "lng": 112.9773, "adcode": "430102" }
  ],
  "saved_matches": [
    {
      "id": "plat_12",
      "contact_name": "王先生",
      "contact_phone_masked": "138****5678",
      "address": "五一广场 黄兴中路88号",
      "detail": "东门",
      "lat": 28.1965,
      "lng": 112.9773,
      "tag": "公司",
      "match_reason": "same_place"
    }
  ]
}
```

| Field                                  | Type           | Description                                                                                                                                                                                                                                                                                |
| -------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `candidates`                           | array          | Candidate addresses found by the search                                                                                                                                                                                                                                                    |
| `candidates[].name`                    | string         | Place name. When searching by location, one location returns several names, from specific to broad                                                                                                                                                                                         |
| `candidates[].address`                 | string         | Full address                                                                                                                                                                                                                                                                               |
| `candidates[].lat`                     | number         | Latitude (GCJ-02); feed into `from_address`/`to_address` when placing an order. **When searching by location this is exactly the coordinate you passed in** — picking a different candidate only changes the place name shown to the courier; the pickup point is always where the user is |
| `candidates[].lng`                     | number         | Longitude (GCJ-02)                                                                                                                                                                                                                                                                         |
| `candidates[].adcode`                  | string         | Administrative division code                                                                                                                                                                                                                                                               |
| `saved_matches`                        | array          | Addresses the user has already saved that match this search; empty array when there's no match                                                                                                                                                                                             |
| `saved_matches[].id`                   | string         | Address ID (`plat_` prefix); use directly as `address_id`                                                                                                                                                                                                                                  |
| `saved_matches[].contact_name`         | string         | Contact name (may be empty)                                                                                                                                                                                                                                                                |
| `saved_matches[].contact_phone_masked` | string         | Masked contact phone (e.g. `138****5678`); empty string if no phone was saved                                                                                                                                                                                                              |
| `saved_matches[].address`              | string         | Address                                                                                                                                                                                                                                                                                    |
| `saved_matches[].detail`               | string         | Door number / extra detail (e.g. "Building 3, Room 303"); empty string if never set                                                                                                                                                                                                        |
| `saved_matches[].lat`                  | number         | Latitude (GCJ-02)                                                                                                                                                                                                                                                                          |
| `saved_matches[].lng`                  | number         | Longitude (GCJ-02)                                                                                                                                                                                                                                                                         |
| `saved_matches[].tag`                  | string         | Label                                                                                                                                                                                                                                                                                      |
| `saved_matches[].source`               | string         | Address origin; always `errand` for addresses saved through this capability                                                                                                                                                                                                                |
| `saved_matches[].last_used_at`         | string \| null | Last-used timestamp                                                                                                                                                                                                                                                                        |
| `saved_matches[].use_count`            | integer        | Number of times used                                                                                                                                                                                                                                                                       |
| `saved_matches[].match_reason`         | string         | Why it matched: `keyword` (the keyword hit the name/door number/tag/contact), `same_place` (same coordinates as a candidate), or `both`                                                                                                                                                    |

<Note>
  When the search returns nothing and the user has no saved addresses, the response is `{ "candidates": [], "saved_matches": [] }` — this is not an error.
</Note>

### Error Codes

| code                        | Description                                                                                         |
| --------------------------- | --------------------------------------------------------------------------------------------------- |
| `CONSENT_GRANT_REQUIRED`    | Missing consent grant (no `consent_grant_id`)                                                       |
| `CONSENT_GRANT_INVALID`     | Consent grant is invalid                                                                            |
| `CONSENT_GRANT_EXPIRED`     | Consent grant has expired; re-authorization required                                                |
| `CONSENT_GRANT_WRONG_CAP`   | Consent grant belongs to a different capability; the delivery-errand capability needs its own grant |
| `CAP_NOT_BOUND`             | The delivery-errand capability is not enabled for this agent                                        |
| `KEYWORD_REQUIRED`          | Neither a keyword nor coordinates were supplied                                                     |
| `ERRAND_LOCATE_UNAVAILABLE` | Address search is not enabled yet                                                                   |
| `ADDRESS_SEARCH_FAILED`     | Address search failed; try again later                                                              |

See [Error Handling](/en/gateway/error-handling) for the full list.

### Call Example

By place name:

```json theme={null}
{
  "name": "errand_search_addresses",
  "arguments": {
    "consent_grant_id": "<consent_grant_id>",
    "keyword": "五一广场",
    "city": "长沙"
  }
}
```

By current location:

```json theme={null}
{
  "name": "errand_search_addresses",
  "arguments": {
    "consent_grant_id": "<consent_grant_id>",
    "lat": 30.290000,
    "lng": 120.096000
  }
}
```
