Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion skills/uipath-data-fabric/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ uip df records query <entity-id> \

Pass the exact `EntityFieldDataType` string — the CLI is case-sensitive. Common types: `STRING`, `INTEGER`, `DECIMAL`, `BOOLEAN`, `DATE`, `DATETIME`, `UUID`. For the full type table with SQL backing types, see [`references/entity-schema.md`](references/entity-schema.md).

### Advanced Field Constraints

Optional per-type constraints on create/update — `lengthLimit` (STRING, MULTILINE_TEXT), `maxValue` / `minValue` (INTEGER, BIG_INTEGER, DECIMAL, FLOAT, DOUBLE), `decimalPrecision` (DECIMAL, FLOAT, DOUBLE). See `references/entity-schema.md` for ranges and examples.

---

## Workflow: Discover → Act → Verify
Expand All @@ -151,7 +155,7 @@ uip df records list <entity-id> --cursor <NextCursor> --output json

## Query Request Format

Pass via `--body` or `--file`. Use `--limit` and `--cursor` CLI flags for pagination — not body keys.
Pass via `--body` or `--file`. Use `--limit`, `--cursor`, and `--offset` CLI flags for pagination — not body keys. See [Pagination](#pagination) below.

```json
{
Expand All @@ -172,6 +176,10 @@ Pass via `--body` or `--file`. Use `--limit` and `--cursor` CLI flags for pagina
- For `in` / `not in` use `"valueList": ["a","b","c"]` — **not** a comma-separated `value` string
- Response includes `HasNextPage` and `NextCursor` — pass `NextCursor` to `--cursor` for the next page

## Pagination

`records list` / `records query` paginate via `--limit`, `--cursor`, `--offset`. See [`references/records-query.md`](references/records-query.md).
Comment thread
AditiGoyalUipath marked this conversation as resolved.

---

## Troubleshooting
Expand Down
38 changes: 36 additions & 2 deletions skills/uipath-data-fabric/references/entity-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ Both entity names and field names must:
"isUnique": false,
"isRbacEnabled": false,
"isEncrypted": false,
"defaultValue": ""
"defaultValue": "",
"lengthLimit": 200
}
```

Expand All @@ -84,6 +85,39 @@ Both entity names and field names must:
| `isRbacEnabled` | boolean | `false` | Role-based access control on this field |
| `isEncrypted` | boolean | `false` | Encrypted at rest |
| `defaultValue` | string | — | Default value (always a string representation) |
| `lengthLimit`, `maxValue`, `minValue`, `decimalPrecision` | number | type-specific | Advanced per-type constraints — see below |

### Advanced Field Constraints

Accepted on `entities create` and on `addFields` / `updateFields` in `entities update`. Each constraint applies only to specific types — passing one to an unsupported type errors with *"Field '<name>' of type <TYPE> does not accept <option>"*. `minValue` must be strictly less than `maxValue`.

| Constraint | Allowed types | Range |
|------------|---------------|-------|
| `lengthLimit` | `STRING` (1–4000), `MULTILINE_TEXT` (1–10000) | — |
| `maxValue` / `minValue` | `INTEGER`, `BIG_INTEGER`, `DECIMAL`, `FLOAT`, `DOUBLE` | ±9,007,199,254,740,991 |
| `decimalPrecision` | `DECIMAL`, `FLOAT`, `DOUBLE` | 0–10 |

```bash
uip df entities create "Orders" \
--body '{
"fields": [
{"fieldName": "ProductName", "type": "STRING", "lengthLimit": 500, "isRequired": true},
{"fieldName": "Price", "type": "DECIMAL", "decimalPrecision": 4, "maxValue": 999999, "minValue": 0},
{"fieldName": "Quantity", "type": "INTEGER", "maxValue": 10000, "minValue": 1}
]
}' \
--output json
```

Change a constraint after creation via `updateFields` (use the field UUID from `entities get`):

```bash
uip df entities update <entity-id> \
--body '{"updateFields":[{"id":"<field-id>","lengthLimit":1000}]}' \
--output json
```

`entities get` echoes the current constraint values on each field under `Fields[].fieldDataType.{lengthLimit,maxValue,minValue,decimalPrecision}` — read these before authoring an `updateFields` call.

### Choice Set Fields

Expand Down Expand Up @@ -154,7 +188,7 @@ uip df entities update <entity-id> \
--output json
```

`updateFields` entry supports: `id` (required), `displayName`, `description`, `isRequired`, `isUnique`, `isRbacEnabled`, `isEncrypted`, `defaultValue`.
`updateFields` entry supports: `id` (required), `displayName`, `description`, `isRequired`, `isUnique`, `isRbacEnabled`, `isEncrypted`, `defaultValue`, `lengthLimit`, `maxValue`, `minValue`, `decimalPrecision`. The four constraint keys follow the per-type allow-list in [Advanced Field Constraints](#advanced-field-constraints).

### Supported `entities update` Body Keys

Expand Down
22 changes: 20 additions & 2 deletions skills/uipath-data-fabric/references/records-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ Response: `{ TotalCount, Records, HasNextPage, NextCursor?, CurrentPage?, TotalP
- Use `HasNextPage` to check if more records exist
- Pass the `NextCursor` string value to `--cursor` to fetch the next page

## Pagination

Offset-based under the hood. Available on both `records list` and `records query`:

- `-l, --limit <number>` — page size, default `50`, min `1`. Keep constant across a sweep (changing it re-slices the offset and can skip/duplicate records).
- `--cursor <NextCursor>` — opaque string from previous response. Pass verbatim; never hand-craft.
- `-o, --offset <number>` — non-negative record index. Rounded down to the nearest page boundary (`jumpToPage = floor(offset / limit) + 1`). **Mutually exclusive with `--cursor`** — passing both errors with *"--offset and --cursor are mutually exclusive"*.
- Stop when `HasNextPage: false`. `CurrentPage` / `TotalPages` are informational.

```bash
# Sequential sweep
uip df records list <entity-id> --limit 100 --output json
uip df records list <entity-id> --limit 100 --cursor "<NextCursor>" --output json

# Jump directly to the page containing record #250 (with --limit 100 → page 3)
uip df records list <entity-id> --limit 100 --offset 250 --output json
```

## Filtered Query

```bash
Expand All @@ -23,7 +41,7 @@ uip df records query <entity-id> \
--output json
```

Pagination for query also uses `--limit` and `--cursor` flags — not body keys.
Pagination for query also uses `--limit`, `--cursor`, and `--offset` flags — not body keys.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is --cursor used for querying VDO entities alone?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this is supported in SDK for cursor based pagination. User can use limit based(Which is supported in datafabric API) or cursor based pagination (supported via sdk)


```bash
# Query with pagination
Expand Down Expand Up @@ -52,7 +70,7 @@ uip df records query <entity-id> \
}
```

> `start` and `limit` are **not** valid body keys — use `--limit` and `--cursor` CLI flags instead.
> Pagination is CLI-flag only: `--limit`, `--cursor`, `--offset`. Do not put `start`, `limit`, `offset`, or `pageSize` inside `--body` — the CLI translates these flags into the underlying offset-based API call.

### Operators

Expand Down
56 changes: 44 additions & 12 deletions tests/tasks/uipath-data-fabric/integration_full_lifecycle.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
task_id: skill-datafabric-integration-full-lifecycle
description: >
Integration test: agent performs a complete Data Fabric lifecycle against a
live tenant — verifies login, discovers or creates an entity, retrieves the
schema to collect field IDs from Fields[].ID, adds and updates fields, inserts
records, queries with a filter, updates one record, verifies the update with
records get, and deletes only the test records. Tests the full Discover → Act →
Verify workflow combining schema management and record CRUD in one multi-step run.
live tenant — verifies login, discovers or creates an entity with advanced
per-type field constraints (lengthLimit on STRING, minValue / maxValue on
INTEGER), retrieves the schema to collect field IDs and confirms the
constraints come back under Fields[].fieldDataType, adds and updates fields
(including tightening a constraint via updateFields), inserts records,
queries with a filter, updates one record, verifies the update with
records get, and deletes only the test records. Tests the full Discover →
Act → Verify workflow combining schema management, advanced field
constraints, and record CRUD in one multi-step run.
tags: [uipath-data-fabric, integration, entities, records]

agent:
Expand All @@ -25,19 +29,23 @@ initial_prompt: |
whatever tenant is currently active.

2. List native-only entities. If an entity named "LifecycleTest" already exists,
use its ID. If not, create it with fields:
- Label (STRING)
- Score (INTEGER)
use its ID. If not, create it with fields and advanced constraints:
- Label (STRING, lengthLimit 200)
- Score (INTEGER, minValue 0, maxValue 1000)
- Active (BOOLEAN)

3. Retrieve the full schema for LifecycleTest using entities get.
From the Fields array, note the ID (Fields[].ID) for the Score field.
Confirm the response echoes the constraints back under
Fields[].fieldDataType.{lengthLimit,minValue,maxValue} — print them so
they are visible in the transcript.

4. Add a new field to the entity: Notes (STRING).
4. Add a new field to the entity: Notes (MULTILINE_TEXT, lengthLimit 2000).

5. Update the Score field: set displayName to "Test Score" and isRequired to true.
Use the field ID from step 3 in the updateFields body — the payload key is
"id" (lowercase), not "ID".
5. Update the Score field: set displayName to "Test Score", isRequired to
true, and tighten maxValue from 1000 to 500. Use the field ID from
step 3 in the updateFields body — the payload key is "id" (lowercase),
not "ID".

6. Insert two records:
- { "Label": "alpha", "Score": 10, "Active": true }
Expand Down Expand Up @@ -169,6 +177,30 @@ success_criteria:
weight: 2.0
pass_threshold: 1.0

- type: command_executed
description: "Agent applied lengthLimit on a field (via entities create or addFields on update)"
tool_name: "Bash"
command_pattern: '(?s)uip\s+df\s+entities\s+(create|update).*lengthLimit'
min_count: 1
weight: 2.0
pass_threshold: 1.0

- type: command_executed
description: "Agent applied minValue/maxValue on a numeric field (via entities create or update)"
tool_name: "Bash"
command_pattern: '(?s)uip\s+df\s+entities\s+(create|update).*(minValue|maxValue)'
min_count: 1
weight: 2.0
pass_threshold: 1.0

- type: command_executed
description: "Agent tightened a numeric constraint via updateFields"
tool_name: "Bash"
command_pattern: '(?s)uip\s+df\s+entities\s+update.*updateFields.*(minValue|maxValue)'
min_count: 1
weight: 2.0
pass_threshold: 1.0

post_run:
- command: "python3 $SKILLS_REPO_PATH/tests/tasks/uipath-data-fabric/_shared/cleanup_entities.py"
timeout: 60
72 changes: 59 additions & 13 deletions tests/tasks/uipath-data-fabric/integration_large_pagination.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ task_id: skill-datafabric-integration-large-pagination
description: >
Integration test: agent imports 500 records from a CSV into a live entity,
traverses all pages using cursor-based pagination (limit=60), verifies no
gap or duplicate record IDs across all 9 pages, then applies a filterGroup
query with pagination (limit=60) to verify the 300-record Active=true subset
across 5 pages. Covers large-dataset pagination stability and cursor
continuity at scale.
gap or duplicate record IDs across all 9 pages, jumps directly to a specific
page using -o/--offset and confirms the offset-page subset matches the
cursor-walked equivalent, then applies a filterGroup query with pagination
(limit=60) to verify the 300-record Active=true subset across 5 pages.
Covers large-dataset pagination stability, cursor continuity at scale, and
offset-based page jumps.
tags: [uipath-data-fabric, integration, bulk-pagination]

agent:
Expand Down Expand Up @@ -39,19 +41,46 @@ initial_prompt: |
4. Import the CSV:
uip df records import <entity-id> --file bulk_500.csv --output json

5. Traverse ALL records using cursor-based pagination (limit=60):
5. MANDATORY — Traverse ALL records using cursor-based pagination (limit=60).
This step MUST be completed in full before any later step. Do NOT skip,
summarise, or claim completion without running every page individually.
- First call: uip df records list <entity-id> --limit 60 --output json
- Each response includes a cursor; pass it to the next call with --cursor
- Stop when no cursor is returned
Use Python to collect all record IDs across pages.
Expected: 9 pages (8 pages × 60 records + 1 page × 20 records = 500 total).
- For each subsequent call, pass the prior response's NextCursor verbatim
via --cursor, and continue to include --limit 60 --output json on
every call. Stop only when HasNextPage is false.
- Run each page as its OWN Bash invocation of `uip df records list`
(not via Python subprocess). Each page must show up as a separate
tool call.
Collect every record ID into a Python list named `cursor_walk_ids`.
Expected: 9 pages (8 pages × 60 records + 1 page × 20 records = 500
total) → 9 separate `uip df records list ... --limit 60` Bash calls.

6. Use Python to verify:
- total unique record IDs collected == 500
- no duplicate IDs across pages

7. Query all Active=true records using records query with filterGroup and
paginate with limit=60 using --cursor until exhausted:
Print `len(cursor_walk_ids)` so the value is visible in the transcript.
If step 5 did not actually produce 9 separate tool calls, return to step 5
and finish the walk before continuing.

7. Only after step 6 has confirmed 500 IDs in `cursor_walk_ids`, jump to a
mid-range page using offset-based pagination:
uip df records list <entity-id> --limit 60 --offset 180 --output json
(--offset rounds down to the nearest page boundary, so offset 180 with
limit 60 lands on page 4, returning records 181..240 of the entity.)
Save the returned record IDs as `offset_page_ids`.

Use Python to confirm:
- exactly 60 records came back
- those 60 IDs match records 181..240 of the full cursor-walked list
(i.e. offset_page_ids == cursor_walk_ids[180:240])

Do NOT pass --offset and --cursor on the same command — they are
mutually exclusive.

8. MANDATORY — Query all Active=true records using records query with
filterGroup and paginate with limit=60 using --cursor until exhausted.
This step MUST run; each page is its own `uip df records query` Bash
call:
{
"filterGroup": {
"logicalOperator": 0,
Expand All @@ -61,7 +90,7 @@ initial_prompt: |
Expected: 5 pages × 60 records = 300 records total.
Collect all matching record IDs.

8. Use Python to verify:
9. Use Python to verify:
- every collected record has Active=true
- total count == 300

Expand Down Expand Up @@ -92,6 +121,23 @@ success_criteria:
weight: 3.0
pass_threshold: 1.0

- type: command_executed
description: "Agent jumped to a page using -o/--offset on records list"
tool_name: "Bash"
command_pattern: 'uip\s+df\s+records\s+list\s+.*(-o\s+\d+|--offset\s+\d+)'
min_count: 1
weight: 2.5
pass_threshold: 1.0

- type: command_executed
description: "Agent must NOT combine --offset and --cursor on the same command"
tool_name: "Bash"
command_pattern: 'uip\s+df\s+records\s+(list|query)(?=[^\n]*--cursor)(?=[^\n]*(-o\s+\d+|--offset\s+\d+))'
min_count: 0
Comment thread
AditiGoyalUipath marked this conversation as resolved.
max_count: 0
weight: 2.0
pass_threshold: 1.0
Comment thread
AditiGoyalUipath marked this conversation as resolved.

- type: command_executed
description: "Agent queried Active=true records with filterGroup"
tool_name: "Bash"
Expand Down
Loading
Loading