TeamDynamix staff asset lookup
Look up the devices and locations assigned to staff in TeamDynamix.
The operator gives you a list of people (names, emails, or partial
identifiers, often messy); you resolve each to a TDX person, pull the
assets assigned to them, and return one table plus a section for names
you could not resolve cleanly.
Authentication
Every request uses the http_request tool with credential: tdx-api.
The tool injects that credential host-side as the Authorization: Bearer
header; you never see the token value and must not put credentials in a
request body or a header yourself. There is no login step in this
skill: the tdx-api credential is already a TDX bearer token the
operator minted and stored.
If any call returns HTTP 401, the token has expired. Stop
immediately, do not retry, and tell the operator: "The tdx-api
credential has expired; refresh it (see INSTALL.md) and run again." You
cannot re-authenticate from inside this skill.
Steps
Resolve each person. For each input identifier, call
http_request:
- method
GET
- url
https://your-tenant.teamdynamix.com/TDWebApi/api/people/lookup?searchText=<url-encoded identifier>&maxResults=10
- credential
tdx-api
The response is a JSON array of User objects. people/lookup
returns the identity fields you need (UID, FullName,
PrimaryEmail, LocationName, IsActive); it omits collection
properties (Attributes among them) that this skill does not use.
Prefer entries with IsActive: true. Then:
- Exactly one active match → resolved. Keep
UID, FullName,
PrimaryEmail.
- More than one plausible match → ambiguous. Do not auto-pick.
Add the candidates (
FullName, PrimaryEmail, UID) to the
"Needs confirmation" section and move on.
- No match → add the original identifier to the "Could not
resolve" section. Never silently drop an input.
Pull assets per resolved person. For each resolved UID, call
http_request:
- method
POST
- url
https://your-tenant.teamdynamix.com/TDWebApi/api/APPID/assets/search
- credential
tdx-api
- body
{"OwningCustomerIDs": ["<UID>"], "MaxResults": 100}
The response is a JSON array of Asset objects. Asset search does
not return the Attributes collection (custom attributes): you get
base fields only, so location, model, ownership, and status come from
this response, but the inventory date does not (step 3).
Fetch inventory detail only when it is in play, and cap it. The
"Last inventory date" column comes from a tenant custom attribute in
Attributes[], which asset search omits. Fetch it per asset only
when the inventory column is actually needed: the operator
configured the attribute (see INSTALL.md) or the user asked for
inventory dates. When it is needed, for each asset up to a cap of
25 detail fetches per run, call http_request:
- method
GET
- url
https://your-tenant.teamdynamix.com/TDWebApi/api/APPID/assets/<asset ID>
- credential
tdx-api
The response is a single Asset with Attributes[] populated. Read
the configured attribute by Name; use its ValueText (or Value).
- If the inventory column is not in play, write "not available".
- If the tenant has no such attribute or it is empty, write "not
available".
- If you reach the 25-fetch cap, write "not available (not fetched,
over cap)" for the remaining assets rather than issuing more
requests. Both searches are rate-limited (60 requests per 60 seconds
per IP); do not fan out unbounded detail fetches.
Emit one table, one row per (person, asset):
| Person (input) |
Resolved match |
Location |
Asset model |
Ownership type |
Last inventory date |
- Resolved match =
FullName (PrimaryEmail).
- Location =
LocationName, plus LocationRoomName when present.
- Asset model =
ProductModelName.
- Ownership type = "Person" when
OwningCustomerName is set;
"Department" when only OwningDepartmentName is set.
- Last inventory date = the value from step 3, or one of the "not
available" forms above. Do not invent a date.
- A resolved person with zero assets gets one row with the asset
columns blank and a note "no assets found".
Then two sections below the table:
- Needs confirmation: ambiguous people, with their candidates,
for the operator to disambiguate. Do not pick for them.
- Could not resolve: input identifiers with no match, listed
verbatim so nothing is lost.
Errors and limits
- 401 → stop and ask for a token refresh (above). One occurrence
ends the run.
- 429 → TDX rate-limits these endpoints (60 requests per 60 seconds
per IP for the searches). Wait a few seconds and retry that one call
once; if it is still 429, stop and report that TDX is rate-limiting.
The 25-fetch detail cap in step 3 exists to keep large lists from
triggering this.
- Any other non-2xx on a person's call → skip that person, note the
status in "Could not resolve", and continue with the rest.
- Missing custom attributes → "not available", never an error.
Read-only
This skill reads only; it never calls a create, update, or delete
endpoint. Read-only rests on two things: the tool refuses every write
verb (only GET, HEAD, and the one declared search POST are allowed),
and the TDX endpoints this skill uses are side-effect-free reads. Note
that a GET to any path on the bound TDX host carries the credential;
this skill confines itself by instruction to people/lookup,
assets/search (POST), and assets/<id>, and the operator's egress
allowlist confines every request to their TDX host.
1---2name: tdx-assets3description: Look up staff devices, assets, and locations in TeamDynamix (TDX). Given a list of names, emails, or partial identifiers, resolve each person and return the assets assigned to them with location, model, ownership type, and status. Read-only.4---56# TeamDynamix staff asset lookup78Look up the devices and locations assigned to staff in TeamDynamix.9The operator gives you a list of people (names, emails, or partial10identifiers, often messy); you resolve each to a TDX person, pull the11assets assigned to them, and return one table plus a section for names12you could not resolve cleanly.1314## Authentication1516Every request uses the `http_request` tool with `credential: tdx-api`.17The tool injects that credential host-side as the `Authorization: Bearer`18header; you never see the token value and must not put credentials in a19request body or a header yourself. There is **no login step** in this20skill: the `tdx-api` credential is already a TDX bearer token the21operator minted and stored.2223If any call returns **HTTP 401**, the token has expired. **Stop24immediately**, do not retry, and tell the operator: "The `tdx-api`25credential has expired; refresh it (see INSTALL.md) and run again." You26cannot re-authenticate from inside this skill.2728## Steps29301. **Resolve each person.** For each input identifier, call31 `http_request`:32 - method `GET`33 - url `https://your-tenant.teamdynamix.com/TDWebApi/api/people/lookup?searchText=<url-encoded identifier>&maxResults=10`34 - credential `tdx-api`3536 The response is a JSON array of `User` objects. `people/lookup`37 returns the identity fields you need (`UID`, `FullName`,38 `PrimaryEmail`, `LocationName`, `IsActive`); it omits collection39 properties (`Attributes` among them) that this skill does not use.40 Prefer entries with `IsActive: true`. Then:41 - **Exactly one active match** → resolved. Keep `UID`, `FullName`,42 `PrimaryEmail`.43 - **More than one plausible match** → **ambiguous**. Do not auto-pick.44 Add the candidates (`FullName`, `PrimaryEmail`, `UID`) to the45 "Needs confirmation" section and move on.46 - **No match** → add the original identifier to the "Could not47 resolve" section. Never silently drop an input.48492. **Pull assets per resolved person.** For each resolved `UID`, call50 `http_request`:51 - method `POST`52 - url `https://your-tenant.teamdynamix.com/TDWebApi/api/APPID/assets/search`53 - credential `tdx-api`54 - body `{"OwningCustomerIDs": ["<UID>"], "MaxResults": 100}`5556 The response is a JSON array of `Asset` objects. **Asset search does57 not return the `Attributes` collection** (custom attributes): you get58 base fields only, so location, model, ownership, and status come from59 this response, but the inventory date does not (step 3).60613. **Fetch inventory detail only when it is in play, and cap it.** The62 "Last inventory date" column comes from a tenant custom attribute in63 `Attributes[]`, which asset search omits. Fetch it per asset **only64 when** the inventory column is actually needed: the operator65 configured the attribute (see INSTALL.md) or the user asked for66 inventory dates. When it is needed, for each asset up to a cap of67 **25 detail fetches per run**, call `http_request`:68 - method `GET`69 - url `https://your-tenant.teamdynamix.com/TDWebApi/api/APPID/assets/<asset ID>`70 - credential `tdx-api`7172 The response is a single `Asset` with `Attributes[]` populated. Read73 the configured attribute by `Name`; use its `ValueText` (or `Value`).74 - If the inventory column is not in play, write "not available".75 - If the tenant has no such attribute or it is empty, write "not76 available".77 - If you reach the 25-fetch cap, write "not available (not fetched,78 over cap)" for the remaining assets rather than issuing more79 requests. Both searches are rate-limited (60 requests per 60 seconds80 per IP); do not fan out unbounded detail fetches.81824. **Emit one table**, one row per (person, asset):8384 | Person (input) | Resolved match | Location | Asset model | Ownership type | Last inventory date |85 |---|---|---|---|---|---|8687 - Resolved match = `FullName` (`PrimaryEmail`).88 - Location = `LocationName`, plus `LocationRoomName` when present.89 - Asset model = `ProductModelName`.90 - Ownership type = "Person" when `OwningCustomerName` is set;91 "Department" when only `OwningDepartmentName` is set.92 - Last inventory date = the value from step 3, or one of the "not93 available" forms above. Do not invent a date.94 - A resolved person with zero assets gets one row with the asset95 columns blank and a note "no assets found".96975. **Then two sections below the table:**98 - **Needs confirmation**: ambiguous people, with their candidates,99 for the operator to disambiguate. Do not pick for them.100 - **Could not resolve**: input identifiers with no match, listed101 verbatim so nothing is lost.102103## Errors and limits104105- **401** → stop and ask for a token refresh (above). One occurrence106 ends the run.107- **429** → TDX rate-limits these endpoints (60 requests per 60 seconds108 per IP for the searches). Wait a few seconds and retry that one call109 once; if it is still 429, stop and report that TDX is rate-limiting.110 The 25-fetch detail cap in step 3 exists to keep large lists from111 triggering this.112- Any other non-2xx on a person's call → skip that person, note the113 status in "Could not resolve", and continue with the rest.114- Missing custom attributes → "not available", never an error.115116## Read-only117118This skill reads only; it never calls a create, update, or delete119endpoint. Read-only rests on two things: the tool refuses every write120verb (only `GET`, `HEAD`, and the one declared search POST are allowed),121and the TDX endpoints this skill uses are side-effect-free reads. Note122that a `GET` to any path on the bound TDX host carries the credential;123this skill confines itself by instruction to `people/lookup`,124`assets/search` (POST), and `assets/<id>`, and the operator's egress125allowlist confines every request to their TDX host.