# get_team_utilization

## What it answers

Get named hours, capacity and utilization per person and role category. Optional unit is months (default) or weeks. Full availableRange is returned even when no rows match. Required real YYYY-MM-DD range.from/range.to dates select inclusive containing months (default) or Monday-start weeks. Sort by Employee Name (default) or Role Category. At most 500 served rows with explicit truncation. No compensation. availableRange spans all served period starts even when the selected range has no rows, or is null when none exist. Read definitions, caveats and truncation before interpreting figures. Decimal strings preserve served numeric figures; they do not recover precision previously lost by a report. Read parakeeto://methodology for shared response conventions and INVALID_ARGUMENT guidance.

Read-only.

## Arguments

| Argument | Type | Required | Default | Allowed values |
| --- | --- | --- | --- | --- |
| `account` | string (uuid) | no | — | — |
| `includeDefinitions` | boolean | no | `true` | — |
| `range` | object | yes | — | — |
| `range.from` | string | yes | — | pattern `^\d{4}-\d{2}-\d{2}$` |
| `range.to` | string | yes | — | pattern `^\d{4}-\d{2}-\d{2}$` |
| `unit` | string | no | `"months"` | `"months"`, `"weeks"` |
| `sortBy` | string | no | `"Employee Name"` | `"Employee Name"`, `"Role Category"` |

## Returned fields

The result is an envelope: `ok: true` with `data`, or `ok: false` with `error`. Error codes: `MODEL_CALCULATOR_ACCESS_REQUIRED`, `PAYROLL_GRID_MISSING`, `PAYROLL_GRID_REQUIRED`, `PROJECT_GRID_REQUIRED`, `EXPENSE_GRID_REQUIRED`, `PAYROLL_ENTRY_REFERENCE_STALE`, `ACCOUNT_NOT_FOUND`, `ACCOUNT_CONFIGURATION_MISSING`, `NO_IMPORTED_TIME`, `NOTHING_IMPORTED`, `ACCOUNT_REQUIRED`, `NO_REACHABLE_ACCOUNTS`, `FEATURE_NOT_ENTITLED`, `PERMISSION_DENIED`, `CALCULATION_FAILED`, `INTERNAL_ERROR`, `INVALID_ARGUMENT`.

- `data`: object
  - `data.account`: string (uuid)
  - `data.unit`: string (`"months"`, `"weeks"`)
  - `data.definitions`: object, optional
    - `data.definitions.grossCapacity`: string
    - `data.definitions.deliveryCapacity`: string
    - `data.definitions.deliveryHours`: string
    - `data.definitions.targetUtilization`: string
    - `data.definitions.utilization`: string
    - `data.definitions.annualDaysBasis`: string
    - `data.definitions.range`: string
    - `data.definitions.qualifications`: string
    - `data.definitions.presentation`: string
  - `data.annualDays`: string (pattern `^-?\d+(?:\.\d+)?$`)
  - `data.freshness`: array of object
    - `data.freshness[].source`: string (`"time-entries"`, `"role-task-mappings"`, `"annual-days"`, `"dashboard-inputs"`)
    - `data.freshness[].everCompleted`: boolean
    - `data.freshness[].completedAt`: string (date-time) or null
  - `data.gridFreshness`: array of object
    - `data.gridFreshness[].kind`: string (`"payroll"`, `"expense"`, `"project"`)
    - `data.gridFreshness[].gridId`: string (uuid)
    - `data.gridFreshness[].name`: string
    - `data.gridFreshness[].storage`: string (`"sheet"`, `"database"`)
    - `data.gridFreshness[].sheetRefreshedAt`: string (date-time) or null
  - `data.caveats`: array of object
    - One of:
      - Variant 1 (`code` is `"omission"`):
        - `data.caveats[].code`: string (`"omission"`)
        - `data.caveats[].source`: string (`"payroll"`, `"time"`)
        - `data.caveats[].employeeName`: string, optional
        - `data.caveats[].rowPosition`: integer (`exclusiveMinimum: 0`)
        - `data.caveats[].message`: string
      - Variant 2 (`code` is `"allocation-mismatch"`):
        - `data.caveats[].code`: string (`"allocation-mismatch"`)
        - `data.caveats[].employeeName`: string
        - `data.caveats[].startDate`: string or null (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.caveats[].weeklyHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
        - `data.caveats[].targetHoursSum`: string (pattern `^-?\d+(?:\.\d+)?$`)
        - `data.caveats[].message`: string
      - Variant 3 (`code` is `"data-condition"`, `id` is `"payroll-duplicate-start-date-double-count"`):
        - `data.caveats[].code`: string (`"data-condition"`)
        - `data.caveats[].id`: string (`"payroll-duplicate-start-date-double-count"`)
        - `data.caveats[].rowCount`: integer (`exclusiveMinimum: 0`)
        - `data.caveats[].employeeName`: string
        - `data.caveats[].startDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.caveats[].roleCategories`: array of string
        - `data.caveats[].latestPeriod`: string, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.caveats[].periods`: array of object, optional
          - `data.caveats[].periods[].date`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
          - `data.caveats[].periods[].roles`: array of string
          - `data.caveats[].periods[].rollingRoles`: array of string
          - `data.caveats[].periods[].overall`: boolean
          - `data.caveats[].periods[].rollingOverall`: boolean
        - `data.caveats[].teamRoles`: array of string, optional
        - `data.caveats[].message`: string
  - `data.availableRange`: object or null
    - `data.availableRange.from`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
    - `data.availableRange.to`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
  - `data.from`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
  - `data.to`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
  - `data.sortBy`: string (`"Employee Name"`, `"Role Category"`)
  - `data.rows`: array of object
    - `data.rows[].grossCapacity`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.rows[].deliveryCapacity`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.rows[].deliveryHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.rows[].targetUtilization`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.rows[].utilization`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.rows[].employeeName`: string
    - `data.rows[].roleCategory`: string
  - `data.truncation`: object
    - `data.truncation.limit`: number (`500`)
    - `data.truncation.totalRows`: integer (`minimum: 0`)
    - `data.truncation.returnedRows`: integer (`minimum: 0`)
    - `data.truncation.omittedRows`: integer (`minimum: 0`)
    - `data.truncation.message`: string or null

On failure:

- `error`: object
  - `error.code`: string (`"MODEL_CALCULATOR_ACCESS_REQUIRED"`, `"PAYROLL_GRID_MISSING"`, `"PAYROLL_GRID_REQUIRED"`, `"PROJECT_GRID_REQUIRED"`, `"EXPENSE_GRID_REQUIRED"`, `"PAYROLL_ENTRY_REFERENCE_STALE"`, `"ACCOUNT_NOT_FOUND"`, `"ACCOUNT_CONFIGURATION_MISSING"`, `"NO_IMPORTED_TIME"`, `"NOTHING_IMPORTED"`, `"ACCOUNT_REQUIRED"`, `"NO_REACHABLE_ACCOUNTS"`, `"FEATURE_NOT_ENTITLED"`, `"PERMISSION_DENIED"`, `"CALCULATION_FAILED"`, `"INTERNAL_ERROR"`, `"INVALID_ARGUMENT"`)
  - `error.argument`: string, optional (`minLength: 1`)
  - `error.message`: string
  - `error.accounts`: array of object, optional
    - `error.accounts[].id`: string (uuid)
    - `error.accounts[].name`: string
  - `error.payrollGrids`: array of object, optional
    - `error.payrollGrids[]`: same shape as `error.accounts[]`
  - `error.projectGrids`: array of object, optional
    - `error.projectGrids[]`: same shape as `error.accounts[]`
  - `error.expenseGrids`: array of object, optional
    - `error.expenseGrids[]`: same shape as `error.accounts[]`
  - `error.context`: object, optional
    - `error.context.account`: object
      - Further fields: see the response.
    - `error.context.imports`: array of object
      - Further fields: see the response.
    - `error.context.hasTimeEntries`: boolean
    - `error.context.reports`: array of object
      - Further fields: see the response.

## Definitions

Returned in `definitions` when `includeDefinitions` is true (the default). Each value is the definition text for that field.

- `grossCapacity`
- `deliveryCapacity`
- `deliveryHours`
- `targetUtilization`
- `utilization`
- `annualDaysBasis`
- `range`
- `qualifications`
- `presentation`

## Caveats

- `omission`. Also carries `source`, `employeeName`, `rowPosition`.
- `allocation-mismatch`. Also carries `employeeName`, `startDate`, `weeklyHours`, `targetHoursSum`.
- `data-condition`. Also carries `id`, `rowCount`, `employeeName`, `startDate`, `roleCategories`, `latestPeriod`, `periods`, `teamRoles`.

Read every caveat before interpreting a figure. See [methodology](</methodology.md>) on how to communicate caveats and data-quality conditions.

## Example call

```json
{
  "name": "get_team_utilization",
  "arguments": {
    "range": {
      "from": "2026-01-01",
      "to": "2026-12-31"
    }
  }
}
```

Add `account` with an identifier from `list_accounts`; omit it only when the connection reaches exactly one account.
