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

# Find

> The seven tools that name what exists, with their arguments, bounds, and captured responses.

Seven of the eleven tools answer "what is there" and never return a captured value. Pick a trace
or a function here, open it with [shape](https://docs.vexlo.ai/mcp/tools/shape.md), fetch bytes with
[values](https://docs.vexlo.ai/mcp/tools/values.md).

| Tool | Route | Answers | Reach for it |
| - | - | - | - |
| `vexlo_search_traces` | `GET /v1/traces` | trace summaries matching a filter | "find the request that failed", when you hold no id |
| `vexlo_check_trace_status` | `GET /v1/traces?trace_id=` | the same summary row, per id | re-checking ids you already hold, instead of searching again |
| `vexlo_find_related_traces` | `GET /v1/traces/{id}/related` | traces sharing a tag with this one | following one request past this service's edge |
| `vexlo_list_functions` | `GET /v1/functions` | every function that ran, by call volume | "what does this service do", "is this function used" |
| `vexlo_list_tags` | `GET /v1/tags` | every tag key, its services, its value count | before filtering by tag, or trusting a tag search |
| `vexlo_check_coverage` | `GET /v1/coverage` | real service and environment names, per-service totals | before reading an empty result as "nothing happened" |
| `vexlo_check_health` | `GET /v1/health` | whether the server is keeping up | before reading a thin result as "nothing happened" |

Every response below was captured against a server seeded with the spec's conformance trace on
team `fixture`: 17 steps, `root_status: error`, one three-attempt step, environment `prod`. The
token's team-set is `demo` and `fixture`. Each bound below is the one that tool's schema
carries, which [install](https://docs.vexlo.ai/mcp/install.md) separates into server-reported and fixed.

## Shared arguments

Five of the seven tools on this page take `team` and `environment`:
`vexlo_check_trace_status` and `vexlo_find_related_traces` scope themselves through the ids they
are handed. [`vexlo_get_function`](https://docs.vexlo.ai/mcp/tools/shape) and
[`vexlo_get_function_examples`](https://docs.vexlo.ai/mcp/tools/values) take the same two, so this section defines
them for the whole site.

`team` is an array of team ids; omit it for every team the token can see. An id outside the
token's team-set is dropped, and the response says which:

```json theme={"system"}
{
  "items": [
... 21 lines omitted
  ],
  "limit": 10,
  "next_cursor": null,
  "scope_note": "requested team(s) not in this token's team set (demo, fixture) and dropped from the query: team-nope"
}
```

When every requested id is outside the set, no request is sent and the tool returns its own
route-shaped empty result, so a scope limit never reads as a real empty answer:

```json theme={"system"}
{
  "services": [],
  "scope_note": "none of the requested teams (team-nope) are in this token's team set (demo, fixture); no rows can exist for them under this credential — this is a scope limit, not an empty result"
}
```

| Argument | Shape | Sent as | Why |
| - | - | - | - |
| `environment` | `{"named": ["prod", "dev"]}` or `{"unset": true}` | `?environment=prod,dev` or `?environment_unset=true` | naming both is unrepresentable, so the API's `conflicting_filters` error is out of reach |
| `environment` on `vexlo_list_tags` | plain array of names | `?environment=prod,dev` | `GET /v1/tags` documents no `environment_unset` |
| `service` on `vexlo_search_traces` | array of names | `?service=a,b`, OR-ed | the one route that ORs them |
| `service` elsewhere | single name | `?service=a` | on those routes a comma-joined value matches nothing and a repeated one matches the first only |
| `cursor` | the previous page's `next_cursor`, verbatim | `?cursor=...` | a stale or hand-built cursor is an argument error |

No live session carries a service pin, since a service-pinned read token never finishes
[startup](https://docs.vexlo.ai/mcp/startup-and-exit-codes.md). So a misspelled service name
and a real, empty one look identical until `vexlo_check_coverage` answers. On every paginated
tool the last page carries `next_cursor: null` rather than omitting it.

## vexlo\_search\_traces

Returns root status, completeness, step and error counts, tags, and duration per trace. Never
step-level detail, never captured values. Narrow before widening `limit`: at the ceiling of 100,
one page costs more tokens than a whole trace's shape. The default of 10 is below the API's own
50, which the [ladder](https://docs.vexlo.ai/mcp/token-costs.md) measures at 7,127 tokens for the search alone.

| Argument | Type | Default |
| - | - | - |
| `team` | array of team ids | every team in the token's set |
| `environment` | `{named}` or `{unset}` | no filter |
| `service` | array of names, OR-ed | no filter |
| `since`, `until` | RFC 3339 instants | no bound |
| `completeness` | `running`, `complete`, `partial`, `abandoned` | no filter |
| `rootStatus` | `ok` or `error` | no filter |
| `hasError` | boolean: at least one errored step | no filter |
| `rootFunction`, `function` | exact `module.qualname`, no prefix or substring match | no filter |
| `durationMinMs`, `durationMaxMs` | integers | no bound |
| `tagKey`, `tagValue` | strings | no filter |
| `limit` | 1 to the lower of 100 and `search_limit_max` | 10 |
| `cursor` | opaque string | first page |

```json theme={"system"}
{
  "items": [
    {
      "trace_id": "0f1a2b3c4d5e6f708192a3b4c5d6e7f8",
      "service": "delivery-service",
      "team": "fixture",
      "environment": "prod",
      "instance_id": "delivery-service-7f9c8d6b5-x2n4q",
      "tags": {
        "order_id": "O-1234"
      },
      "root_function": "delivery.api.AssignDasherHandler",
      "root_status": "error",
      "completeness": "complete",
      "started_at": "2026-09-07T19:30:01.402Z",
      "duration_ms": 121,
      "step_count": 17,
      "error_step_count": 4,
      "records_lost": 0,
      "records_shed": 0,
      "truncated": false,
      "instance_mismatch": false
    }
  ],
  "limit": 10,
  "next_cursor": null
}
```

`matched_tag_keys` appears on a row only when `tagValue` was set and `tagKey` was not: naming
the key suppresses the field. `root_status` and `duration_ms` are omitted rather than emptied
until the root attempt's completion record arrives, so a `running` or an `abandoned` row carries
neither. `root_function` needs less: any record for the root step sets it, a `step-open`
included, so a row can name its root function while carrying no `root_status` at all.

## vexlo\_check\_trace\_status

Takes `traceIds`, 1 to 100, and nothing else: no other filter applies here. The tool sends
`?limit=<count of ids>`, so `limit` reads 2 below. Rows are the shape search returns:

```json theme={"system"}
{
  "items": [
    {
      "trace_id": "0f1a2b3c4d5e6f708192a3b4c5d6e7f8",
      "service": "delivery-service",
      "team": "fixture",
... 15 lines omitted
      "instance_mismatch": false
    }
  ],
  "limit": 2,
  "next_cursor": null,
  "not_returned": [
    "deadbeefdeadbeefdeadbeefdeadbeef"
  ]
}
```

`not_returned` is the tool's own field: the ids asked for minus the ids returned, omitted when
every id came back. An id lands there because no such trace exists or because it
belongs to a team this token cannot see, two cases the API keeps indistinguishable.
`next_cursor` is always `null`, since every id named resolves on one page.

## vexlo\_find\_related\_traces

The only way to see what else touched one request once this trace's steps end at its service's
edge. It reports that traces share a tag, never that one called the other; call relationships
live on `vexlo_get_function`.

| Argument | Type | Default |
| - | - | - |
| `traceId` | the anchor trace | required |
| `windowHours` | 1 to 168, sent as `?window=<n>h` | 24 |
| `limit` | 1 to the lower of 100 and `search_limit_max` | `search_limit_default`, 50 here |
| `cursor` | opaque string | first page |

No `team` or `environment`: the search is scoped to the anchor trace's own team. The 168-hour
ceiling is the route's own 7-day cap, which keeps the server's silent clamp out of reach. An
empty result is ambiguous by construction: nothing else ran, nothing else carries that tag
value, or another trace spells the value under a key this one does not use. Service plays no
part: two traces from one service relate through a shared tag like any others. The window is
anchored to wall-clock now, never to the anchor's `started_at`, so a trace older than seven days
is unreachable whatever `windowHours` says. On an empty result the tool spends one point read on
the anchor to check whether that is the reason:

```json theme={"system"}
{
  "relation": "shares_tag",
  "searched_tag_keys": [
    "order_id"
  ],
  "window": {
    "since": "2026-11-04T05:52:09.882Z",
    "until": "2026-11-05T05:52:09.882Z"
  },
  "items": [],
  "limit": 50,
  "next_cursor": null,
  "note": "no related traces found, but this trace started at 2026-09-07T19:30:01.402Z, outside the searched window (2026-11-04T05:52:09.882Z to 2026-11-05T05:52:09.882Z); a wider windowHours will not help once the trace is more than 7 days old — this route can never search relative to the trace's own time, only to now"
}
```

`note` is omitted when `items` is non-empty, and when the anchor falls inside the window. An
item carries `trace_id`, `service`, `shared_tags`, `started_at`, and `root_status`, that last
absent while its own root runs.

## vexlo\_list\_functions

One row per function, ranked by `observed_count` descending, each row that function's aggregate
across every caller. Names and counts only: no caller or callee edges, no examples.

| Argument | Type | Default |
| - | - | - |
| `team` | array of team ids | every team in the token's set |
| `environment` | `{named}` or `{unset}` | no filter |
| `service` | single name | no filter |
| `name` | exact `module.qualname` | no filter |
| `limit` | 1 to the lower of 200 and `search_limit_max` | `search_limit_default`, 50 here |
| `cursor` | opaque string | first page |

```json theme={"system"}
{
  "items": [
    {
      "service": "delivery-service",
      "team": "fixture",
      "name": "delivery.api.WriteAPIResponse",
      "observed_count": 1,
      "error_count": 0,
      "first_seen_at": "2026-11-05T05:51:22.869Z",
      "last_seen_at": "2026-11-05T05:51:22.869Z",
      "is_entry_point": false
    },
    {
      "service": "delivery-service",
      "team": "fixture",
      "name": "delivery.dispatch.WriteAuditRecord",
      "observed_count": 1,
      "error_count": 0,
      "first_seen_at": "2026-11-05T05:51:22.869Z",
      "last_seen_at": "2026-11-05T05:51:22.869Z",
      "is_entry_point": false
    },
... 150 lines omitted
  ],
  "limit": 50,
  "next_cursor": null
}
```

`is_entry_point` says the function has been observed opening a trace. A row carries `team` only
when the read resolved to one team; where it is absent the row sums every team in scope, so pass
one `team` id to attribute `observed_count` and `error_count`.

## vexlo\_list\_tags

Arguments: `team`, `environment` (named values only), `service` (single name), and `limit` and
`cursor` with the same computed bounds as `vexlo_list_functions`. A tag only one service emits
has not been seen crossing a service boundary in this team's traces.

```json theme={"system"}
{
  "items": [
    {
      "key": "order_id",
      "services": [
        "delivery-service"
      ],
      "distinct_value_count": 1
    }
  ],
  "limit": 50,
  "next_cursor": null
}
```

## vexlo\_check\_coverage

The one place to learn which service and environment names exist for a team; there is no
list-services route. Arguments: `team`,
`environment`, `service`. No `limit` or `cursor`: the route is never paginated.

```json theme={"system"}
{
  "services": [
    {
      "service": "delivery-service",
      "traces_24h": 1,
      "marked_functions_seen": 17,
      "records_lost_24h": 0,
      "records_shed_24h": 0,
      "last_seen_at": "2026-11-05T05:51:22.869Z"
    }
  ]
}
```

A row carries `environment` when the query filtered by one. `marked_functions_seen` counts only
marked functions: a low number means little of the service is marked, never that the service
does little.

## vexlo\_check\_health

Disk and value-store budget, retention, and per-service record loss, from the same three
arguments `vexlo_check_coverage` takes.

```json theme={"system"}
{
  "status": "healthy",
  "mode": "normal",
  "shape_store": {
    "disk_used_bytes": 143360,
    "effective_retention_days": 7
  },
  "value_store": {
    "bytes_used": 6168,
    "byte_budget": 21474836480,
    "effective_retention_estimate_hours": 0
  },
  "services": [
    {
      "service": "delivery-service",
      "records_lost_24h": 0,
      "records_shed_24h": 0,
      "last_seen_at": "2026-11-05T05:51:22.869Z"
    }
  ]
}
```

Under disk pressure the server answers `status: "degraded"` and `mode: "shape_only"` with HTTP
503, which this tool returns as data, not a failure
([errors, rate limits, retries](https://docs.vexlo.ai/mcp/errors-and-rate-limits.md) explains how). In that mode a value
handle elsewhere reads as unavailable for newly captured data, not as nothing captured. The
team-level `stubs_swept_24h` field the route sends is absent from this result.

## What each response above cost

Measured over the one-line text each tool returned; the blocks above are `jq .` renderings of
it.

| Call | Bytes | Tokens |
| - | -: | -: |
| `vexlo_list_tags`, 1 tag | 117 | 34 |
| `vexlo_check_coverage`, 1 service | 171 | 65 |
| `vexlo_check_coverage`, scope-limit skip | 212 | 52 |
| `vexlo_check_health`, 1 service | 333 | 113 |
| `vexlo_find_related_traces`, empty with `note` | 501 | 168 |
| `vexlo_search_traces`, 1 trace | 506 | 182 |
| `vexlo_search_traces`, 1 trace with `scope_note` | 622 | 214 |
| `vexlo_check_trace_status`, 2 ids, 1 returned | 557 | 195 |
| `vexlo_list_functions`, 17 functions | 4,048 | 1,450 |

[Token costs](https://docs.vexlo.ai/mcp/token-costs.md) has the full ladder, including these tools' widest pages.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.