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

# Gryzzly

> Read and write Gryzzly time-tracking data from Agent Factory agents and Builder workflows — projects, tasks, declarations, leave periods and payroll exports

<img src="https://mintcdn.com/prismeai/Oqq72tWGTtxufvRl/images/connectors/gryzzly.svg?fit=max&auto=format&n=Oqq72tWGTtxufvRl&q=85&s=6de060c96ecf7ada316a8bff92ffad7e" alt="Gryzzly" width="96" height="96" noZoom style={{ float: "left", marginRight: "1.25rem", marginBottom: "0.5rem" }} data-path="images/connectors/gryzzly.svg" />

The Gryzzly app exposes the [Gryzzly](https://www.gryzzly.io) time-tracking SaaS (v1 REST-RPC API) through entity tools. It can be consumed two ways: as a remote MCP server that **Agent Factory** agents call as tools, or as a Builder app whose instructions you call directly from DSUL. It runs in the **tenant app-instance context** (it resolves the installing workspace's own Gryzzly API key) and covers customers, projects, tasks, declarations (time entries), leave periods, discounts, purchases, users, groups, groupsets, tags, tagsets and project metrics.

Authentication is a **Gryzzly API key** sent server-side as `Authorization: Bearer <token>` — never exposed to the agent. Agents are identified by the capability **Scope** `context_id,agent_id,user_id` and gated by a per-workspace authorized-agents allowlist.

<CardGroup cols={3}>
  <Card title="Time tracking" icon="clock">
    Declarations (time entries), leave periods and payroll-grade exports for invoicing and HR.
  </Card>

  <Card title="Project structure" icon="diagram-project">
    Customers, projects, tasks, discounts, purchases and project metrics with budgets and contributors.
  </Card>

  <Card title="Admin & org" icon="users">
    Users and roles, groups, groupsets, tags and tagsets.
  </Card>
</CardGroup>

## Who is this for?

This connector is used by three different roles. Jump to the section that matches yours — each one is self-contained.

<CardGroup cols={3}>
  <Card title="Agent builder" icon="robot">
    You build agents in **Agent Factory** and want them to use Gryzzly. → *Agent builder* tab.
  </Card>

  <Card title="Platform admin" icon="shield-halved">
    You run the platform and set up Gryzzly once for everyone. → *Platform admin setup* accordion below.
  </Card>

  <Card title="Workspace builder" icon="puzzle-piece">
    You write Builder automations (DSUL) that call Gryzzly operations directly. → *Workspace builder* tab.
  </Card>
</CardGroup>

## Prerequisites

* A **Gryzzly** account with administrator access.
* A **Gryzzly API key** — generated in the Gryzzly dashboard under **Administration > API Keys**.
* The API key owner must have the Gryzzly role required for the resources you intend to use (a key with insufficient role gets `403` on writes).
* Base URL (default: `https://api.gryzzly.io/v1`).

<Accordion title="Platform admin (Governance) — one-time platform setup" icon="shield-halved">
  **Goal:** Gryzzly is a **per-workspace** connector — each workspace configures its own Gryzzly API key (see the *Workspace builder* tab), so there is **no platform-wide credential to provision**. The only optional platform task is to publish Gryzzly as a reusable **capability** in your org's Capabilities catalog so agent builders can enable it from the catalog instead of pasting a raw MCP endpoint.

  <Note>
    There is no shared Gryzzly credential and no central OAuth client for this connector. The Gryzzly API key and the authorized-agents allowlist always live in the consuming workspace. A capability you publish here points at a specific workspace's MCP endpoint; that workspace still owns the credential and the allowlist — even after the capability is in the catalog, only the agents that workspace allowlists can actually call it.
  </Note>

  ## Declare the capability in the Capabilities catalog (optional)

  <Note>
    **Easiest path — the one-click "Add to catalog" button.** The configuration app (in the *MCP endpoint* section) has an **Add to catalog** button that registers the connector org-wide in one click: it creates an `mcp`-type catalog entry pointing at this workspace's MCP endpoint with the *Scope* `context_id,agent_id,user_id` already set. If an entry already exists it offers **Update catalog entry** instead. The button is shown only to **org owners / admins**, and the published entry is **org-wide** — every builder in the org can then attach the connector (subject to the workspace allowlist). Use this instead of the manual steps below; they remain for when you want to author the capability by hand.
  </Note>

  <Steps>
    <Step title="Open AI Governance > Capabilities">
      Create (or edit) the **Gryzzly** capability.
    </Step>

    <Step title="Point it at the MCP endpoint">
      Set the capability's MCP server URL to the connector's **MCP Endpoint** (the workspace running the connector), and set its **Scope** to:

      ```text theme={null}
      context_id,agent_id,user_id
      ```

      The `agent_id` in the scope is what lets the connector identify and authorize the calling agent.
    </Step>

    <Step title="Make it available to agent builders">
      Once created, the capability appears in the capability picker for agent builders in your organization, who enable it on their agents. Access to the catalog follows your organization's existing roles; there is no per-capability role grant. Which agents may actually call this tenant-context connector is gated separately by the per-workspace allowlist (see below).
    </Step>
  </Steps>

  <Warning>
    Declaring the capability makes the connector **available**; it does not by itself authorize a specific agent. This connector follows the **tenant-context model** — which agents may actually call it is gated per-workspace by the **authorized-agents allowlist** in the configuration app (see the *Workspace builder* tab). There is **no OAuth auth-config JSON** to attach in Governance: authentication is a server-side Gryzzly API key, not a per-user OAuth flow.
  </Warning>
</Accordion>

***

<Tabs>
  <Tab title="Agent builder (Agent Factory)">
    ## Agent builder

    **Goal:** let an agent you build in Agent Factory use Gryzzly through MCP tools.

    <Note>
      Before an agent can call the connector, a *Workspace builder* must have installed and configured the Gryzzly app in a workspace (see the *Workspace builder* tab). Optionally, a *Platform admin* may have published a Gryzzly capability in AI Governance (see the *Platform admin setup* accordion above).
    </Note>

    This connector runs in the **tenant app-instance context**: your agent is identified by the `agent_id` that Agent Factory injects through the capability *Scope*, and that agent must appear in the connector's **authorized-agents allowlist** (managed in the configuration app). The Gryzzly API key itself is resolved server-side — never exposed to the agent.

    <Note>
      **Easy path — pick it from the catalog.** If an org owner / admin used the config app's one-click **Add to catalog** button (see the *Platform admin setup* accordion above), **Gryzzly** already appears in your org's capability catalog with the MCP endpoint and *Scope* (`context_id,agent_id,user_id`) pre-wired — just select it on your agent, no endpoint to paste. The connector still enforces the workspace's authorized-agents allowlist, so your agent must be ticked there (step 2 below). Otherwise, wire the capability by hand with the steps below.
    </Note>

    <Steps>
      <Step title="Install and configure the connector in your workspace">
        Follow the *Workspace builder* tab: install **Gryzzly** in your workspace, open its **Configuration app**, and paste your Gryzzly API key (and base URL if you are not on the default host).
      </Step>

      <Step title="Allowlist your agent">
        In that workspace's config app, open **Authorized agents** and tick your agent (the **Install capability** button does this for you), or enable **Allow all agents**.
      </Step>

      <Step title="Add the MCP capability to your agent">
        In your agent, add a capability pointing at **your workspace's MCP Endpoint** URL, and set its **Scope** to:

        ```text theme={null}
        context_id,agent_id,user_id
        ```

        The `agent_id` is what lets the connector identify and authorize your agent — without it, every call is rejected with an explicit "agent could not be identified" message.
      </Step>

      <Step title="Brief the agent">
        Tell the agent the tools exist and when to use them. Copy-pasteable starter:

        ```text theme={null}
        You have access to the Gryzzly MCP server. Use it whenever the user asks about time-tracking data — customers, projects, tasks, declarations, leave periods or payroll exports. Each tool takes an `action` argument (list, get, create, update, delete). Examples: "How many hours did I declare last week?", "Create a new project under customer Acme", "List my pending leave requests", "Export this month's declarations". Prefer calling a tool over guessing, and confirm with the user before any destructive action (delete a project, remove a declaration, cancel a leave period).
        ```

        Refine the trigger keywords (customer names, project codes, internal task labels) so the agent reliably picks up the right intent in your context.
      </Step>
    </Steps>

    <Note>
      **Legacy AI Knowledge agents** (no native MCP picker): add the connector under **Advanced > Tools > MCP** and paste the **MCP Endpoint** URL. The agent still has to be allowlisted in the config app and its identity propagated so the connector can read its `agent_id`.
    </Note>

    ## Available Tools

    Each tool maps to a Gryzzly entity and takes an `action` argument selecting the concrete operation (`list`, `get`, `create`, `update`, `delete`, `invite`), plus the per-action parameters. All IDs are UUIDs returned by Gryzzly; most list actions accept `limit` (max 1000) and `offset` for pagination.

    | Tool           | Description                                                                                                                                                  |
    | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `customers`    | Customers (clients). Actions: `list`, `get`, `create`, `update`, `delete`.                                                                                   |
    | `projects`     | Projects. Actions: `list`, `get`, `create`, `update`, `delete`. Billing modes are configured per-task in the Gryzzly UI, not via the API (see Tool Details). |
    | `tasks`        | Tasks (work items under projects). Actions: `list`, `get`, `create`, `update`, `delete`.                                                                     |
    | `declarations` | Declarations / time entries. Actions: `list` (requires `task_ids` + `user_ids`), `create`, `update`, `delete`.                                               |
    | `leavePeriods` | Leave periods (absences). Actions: `list`, `get`, `create`, `update`, `delete`.                                                                              |
    | `discounts`    | Discounts on projects/tasks. Actions: `list`, `get`, `create`, `update`, `delete`.                                                                           |
    | `purchases`    | Purchases / expenses. Actions: `list`, `get`, `create`, `update`, `delete`.                                                                                  |
    | `users`        | Users (members). Actions: `list`, `get`, `invite`.                                                                                                           |
    | `groups`       | User groups. Actions: `list`, `get`.                                                                                                                         |
    | `groupsets`    | Group sets. Actions: `list`, `get`.                                                                                                                          |
    | `tags`         | Tags. Actions: `list`, `get`.                                                                                                                                |
    | `tagsets`      | Tag sets. Actions: `list`, `get`.                                                                                                                            |
    | `metrics`      | Project metrics (time/budget aggregates). Actions: `get`, `list` (requires `project_ids`).                                                                   |

    ## Output Formats

    Every tool accepts an `outputFormat` argument that controls the MCP response shape:

    * **`verbose`** (default) — human-readable text optimized for LLM consumption
    * **`structured`** — machine-readable JSON in `structuredContent`
    * **`both`** — both text and structured content

    ## Tool Details

    ### declarations — create

    Log a time entry on a task for a specific user.

    ```json theme={null}
    {
      "name": "declarations",
      "arguments": {
        "action": "create",
        "user_id": "user-uuid",
        "task_id": "task-uuid",
        "date": "2026-04-20",
        "duration": 7200,
        "description": "Implementation review"
      }
    }
    ```

    | Parameter     | Required | Description                      |
    | ------------- | -------- | -------------------------------- |
    | `action`      | Yes      | `create`.                        |
    | `date`        | Yes      | Declaration date (`YYYY-MM-DD`). |
    | `duration`    | Yes      | Duration in seconds.             |
    | `task_id`     | Yes      | UUID of the task.                |
    | `user_id`     | Yes      | UUID of the user.                |
    | `description` | No       | Free-form text, max 256 chars.   |

    ### projects — create

    ```json theme={null}
    {
      "name": "projects",
      "arguments": {
        "action": "create",
        "name": "Website Revamp",
        "start_at": "2026-01-06",
        "customer_id": "customer-uuid",
        "visibility": "private",
        "managers": ["manager-uuid"]
      }
    }
    ```

    | Parameter                                                                     | Required | Description                                                        |
    | ----------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------ |
    | `action`                                                                      | Yes      | `create`.                                                          |
    | `start_at`                                                                    | Yes      | Project start date (`YYYY-MM-DD`).                                 |
    | `name`                                                                        | No       | Project name.                                                      |
    | `visibility`                                                                  | No       | `public` / `private` — `contributors` must be empty when `public`. |
    | `customer_id`, `code`, `end_at`, `managers`, `contributors`, `groups`, `tags` | No       | Optional structure.                                                |

    <Warning>
      **Billing trap:** the API cannot set `is_billable: true` — Gryzzly rejects it with `409 "can't handle billable project"`. Billing modes (fixed-fee, package, time-and-material) live at the **task** level and must be configured in the Gryzzly UI (`app.gryzzly.io`). Always create/update projects with `is_billable: false` (the default), then configure billing tasks in the UI. The billable → non-billable transition is irreversible and wipes financial data.
    </Warning>

    ### tasks — create

    ```json theme={null}
    {
      "name": "tasks",
      "arguments": {
        "action": "create",
        "project_id": "project-uuid",
        "name": "Design System",
        "start_at": "2026-01-06",
        "budget_type": "time",
        "planned_duration": 80
      }
    }
    ```

    | Parameter                    | Required | Description                                                           |
    | ---------------------------- | -------- | --------------------------------------------------------------------- |
    | `action`                     | Yes      | `create`.                                                             |
    | `name`                       | Yes      | Task name.                                                            |
    | `project_id`                 | Yes      | UUID of the parent project.                                           |
    | `start_at`                   | Yes      | Task start date (`YYYY-MM-DD`).                                       |
    | `budget_type`                | No       | `none` / `detailed` / `global` / `time`.                              |
    | `hourly_rate_mode`           | No       | `task` / `group` / `contributor`.                                     |
    | `parent_id` / `is_container` | No       | Build sub-tasks (`parent_id`) and parent containers (`is_container`). |

    ### leavePeriods — create

    ```json theme={null}
    {
      "name": "leavePeriods",
      "arguments": {
        "action": "create",
        "user_id": "user-uuid",
        "start_at": "2026-05-10",
        "end_at": "2026-05-14",
        "start_type": "full",
        "end_type": "full",
        "description": "Vacation"
      }
    }
    ```

    | Parameter                 | Required | Description                                              |
    | ------------------------- | -------- | -------------------------------------------------------- |
    | `action`                  | Yes      | `create`.                                                |
    | `start_at` / `end_at`     | No       | Leave period bounds (`YYYY-MM-DD`).                      |
    | `start_type` / `end_type` | No       | `full` / `am` / `pm`.                                    |
    | `delete_declaration`      | No       | Set `true` to remove existing declarations in the range. |
    | `description`             | No       | Free-form text, max 128 chars.                           |

    ### users — invite

    ```json theme={null}
    {
      "name": "users",
      "arguments": {
        "action": "invite",
        "email": "new.hire@example.com",
        "role": "contributor",
        "group_ids": ["group-uuid"]
      }
    }
    ```

    | Parameter   | Required | Description                                                        |
    | ----------- | -------- | ------------------------------------------------------------------ |
    | `action`    | Yes      | `invite`.                                                          |
    | `email`     | No       | Invitee email address.                                             |
    | `role`      | No       | `contributor` / `collaborator` / `manager` / `director` / `admin`. |
    | `group_ids` | No       | UUIDs of the groups to add the user to.                            |

    ### declarations — list

    Read time entries over a window for given tasks and users.

    ```json theme={null}
    {
      "name": "declarations",
      "arguments": {
        "action": "list",
        "task_ids": ["task-uuid"],
        "user_ids": ["user-uuid"],
        "from": "2026-03-01",
        "to": "2026-03-31"
      }
    }
    ```

    | Parameter          | Required | Description                                  |
    | ------------------ | -------- | -------------------------------------------- |
    | `action`           | Yes      | `list`.                                      |
    | `task_ids`         | Yes      | UUIDs of the tasks to read declarations for. |
    | `user_ids`         | Yes      | UUIDs of the users to read declarations for. |
    | `from` / `to`      | No       | Date window (`YYYY-MM-DD`).                  |
    | `limit` / `offset` | No       | Pagination (`limit` max 1000).               |
  </Tab>

  <Tab title="Workspace builder (DSUL)">
    ## Workspace builder

    **Goal:** install the connector in a workspace, configure the Gryzzly API key and the agent allowlist, and call Gryzzly operations from your automations.

    ## Installation

    1. Go to **Apps** in your workspace
    2. Search for **Gryzzly** and install it
    3. Open the **Configuration app** (the link auto-populated on install) to paste your Gryzzly API key, set the base URL if needed, and allow the agents that may call the connector

    ## Configuration

    | Field                 | Description                                                                                                                  |
    | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
    | **Configuration app** | Auto-populated on install — open this link to set the Gryzzly API key + base URL and manage the authorized-agents allowlist. |

    The configuration app drives everything; the app instance itself has no per-field credential form. From it you provide:

    | Auth mode            | What you provide                                                                          | Best for                                                                                                     |
    | -------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
    | `apiKey` (only mode) | A Gryzzly **API key** + optionally the **base URL** (default `https://api.gryzzly.io/v1`) | All setups — the key is stored as a workspace secret and sent server-side as `Authorization: Bearer <token>` |

    <Note>
      The API key is provisioned into the workspace's Secrets and resolved server-side. The agent allowlist (**Authorized agents**) gates which Agent Factory agents may call the MCP endpoint — see the *Agent builder* tab.
    </Note>

    ## Available Instructions

    Every instruction resolves credentials from the workspace configuration. All IDs are UUIDs returned by Gryzzly. Most list operations accept `limit` (max 1000) and `offset` for pagination.

    ### Customers

    | Instruction      | Description                                                           | Returns                                              |
    | ---------------- | --------------------------------------------------------------------- | ---------------------------------------------------- |
    | `listCustomers`  | List customers; filter by `customer_ids`, `manager_ids`, `is_active`. | `{ data: [{ id, name, is_active, managers }], ... }` |
    | `getCustomer`    | Get a customer by `id`.                                               | `{ id, name, is_active, managers }`                  |
    | `createCustomer` | Create a customer from `name` (+ optional `managers`).                | The created customer `{ id, name, ... }`             |
    | `updateCustomer` | Update a customer by `id` (+ `name`, `is_active`, `managers`).        | The updated customer                                 |
    | `deleteCustomer` | Delete a customer by `id`.                                            | Empty (HTTP 204)                                     |

    ### Projects

    | Instruction           | Description                                                                                                 | Returns                                              |
    | --------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
    | `listProjects`        | List projects; filter by `status` (`active`/`done`/`archived`).                                             | `{ data: [{ id, name, status, customer_id }], ... }` |
    | `getProject`          | Get a project by `id`.                                                                                      | `{ id, name, status, ... }`                          |
    | `createProject`       | Create a project (`start_at` required; `is_billable` must stay false — see the Agent builder billing trap). | The created project `{ id, name, ... }`              |
    | `updateProject`       | Update a project by `id`.                                                                                   | The updated project                                  |
    | `deleteProject`       | Delete a project by `id`.                                                                                   | Empty (HTTP 204)                                     |
    | `getProjectMetrics`   | Get a project's time/budget metrics by `project_id`.                                                        | `{ time, budget, ... }`                              |
    | `listProjectsMetrics` | Metrics for several projects by `project_ids`.                                                              | `{ data: [{ project_id, time, budget }] }`           |

    ### Tasks

    | Instruction  | Description                                                                                                                | Returns                                     |
    | ------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
    | `listTasks`  | List tasks; filter by `project_ids`, `task_ids`.                                                                           | `{ data: [{ id, name, project_id }], ... }` |
    | `getTask`    | Get a task by `id`.                                                                                                        | `{ id, name, project_id, ... }`             |
    | `createTask` | Create a task (`name`, `project_id`, `start_at` required; `budget_type`, `hourly_rate_mode`, `parent_id`, `is_container`). | The created task                            |
    | `updateTask` | Update a task by `id`.                                                                                                     | The updated task                            |
    | `deleteTask` | Delete a task by `id`.                                                                                                     | Empty (HTTP 204)                            |

    ### Declarations (Time Entries)

    | Instruction         | Description                                                                      | Returns                                                     |
    | ------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------- |
    | `listDeclarations`  | List declarations; `task_ids` + `user_ids` required, optional `from`/`to`.       | `{ data: [{ id, date, duration, task_id, user_id }], ... }` |
    | `createDeclaration` | Log a time entry (`date`, `duration` in seconds, `task_id`, `user_id` required). | The created declaration                                     |
    | `updateDeclaration` | Update a declaration by `id` (`date`, `duration`, `task_id` required).           | The updated declaration                                     |
    | `deleteDeclaration` | Delete a declaration by `id`.                                                    | Empty (HTTP 204)                                            |

    ### Leave Periods

    | Instruction          | Description                                                                                         | Returns                                              |
    | -------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
    | `listLeavesPeriods`  | List leave periods; filter by `user_ids`, `from`/`to`.                                              | `{ data: [{ id, user_id, start_at, end_at }], ... }` |
    | `getLeavesPeriod`    | Get a leave period by `id`.                                                                         | `{ id, user_id, start_at, end_at, ... }`             |
    | `createLeavesPeriod` | Create a leave period (`user_id`, `start_at`/`end_at`, `start_type`/`end_type` ∈ `full`/`am`/`pm`). | The created leave period                             |
    | `updateLeavesPeriod` | Update a leave period by `id`.                                                                      | The updated leave period                             |
    | `deleteLeavesPeriod` | Delete a leave period by `id`.                                                                      | Empty (HTTP 204)                                     |

    ### Discounts

    | Instruction      | Description                                            | Returns                                 |
    | ---------------- | ------------------------------------------------------ | --------------------------------------- |
    | `listDiscounts`  | List discounts; filter by `project_ids`, `task_ids`.   | `{ data: [{ id, name, amount }], ... }` |
    | `getDiscount`    | Get a discount by `id`.                                | `{ id, name, amount }`                  |
    | `createDiscount` | Create a discount (`name`; `project_id` or `task_id`). | The created discount                    |
    | `updateDiscount` | Update a discount by `id` (`name`, `amount`).          | The updated discount                    |
    | `deleteDiscount` | Delete a discount by `id`.                             | Empty (HTTP 204)                        |

    ### Purchases

    | Instruction      | Description                                                                                                                           | Returns                                                      |
    | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
    | `listPurchases`  | List purchases; filter by `project_ids`, `task_ids`.                                                                                  | `{ data: [{ id, name, billed_price }], ... }`                |
    | `getPurchase`    | Get a purchase by `id`.                                                                                                               | `{ id, name, billed_at, billed_price, paid_at, paid_price }` |
    | `createPurchase` | Create a purchase (`project_id` or `task_id`; `billed_at`/`billed_price`, `paid_at`/`paid_price`, `billing_policy` ∈ `add`/`ignore`). | The created purchase                                         |
    | `updatePurchase` | Update a purchase by `id`.                                                                                                            | The updated purchase                                         |
    | `deletePurchase` | Delete a purchase by `id`.                                                                                                            | Empty (HTTP 204)                                             |

    ### Users

    | Instruction  | Description                                                                                                        | Returns                                |
    | ------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------- |
    | `listUsers`  | List users.                                                                                                        | `{ data: [{ id, email, role }], ... }` |
    | `getUser`    | Get a user by `id`.                                                                                                | `{ id, email, role, ... }`             |
    | `inviteUser` | Invite a user (`email`, `role` ∈ `contributor`/`collaborator`/`manager`/`director`/`admin`, optional `group_ids`). | The invited user / invitation          |

    ### Groups & Groupsets

    | Instruction     | Description                                         | Returns                                      |
    | --------------- | --------------------------------------------------- | -------------------------------------------- |
    | `listGroups`    | List groups; filter by `group_ids`, `groupset_ids`. | `{ data: [{ id, name, groupset_id }], ... }` |
    | `getGroup`      | Get a group by `id`.                                | `{ id, name, groupset_id }`                  |
    | `listGroupsets` | List group sets; filter by `groupset_ids`.          | `{ data: [{ id, name }], ... }`              |
    | `getGroupset`   | Get a group set by `id`.                            | `{ id, name }`                               |

    ### Tags & Tagsets

    | Instruction   | Description                                   | Returns                                    |
    | ------------- | --------------------------------------------- | ------------------------------------------ |
    | `listTags`    | List tags; filter by `tag_ids`, `tagset_ids`. | `{ data: [{ id, name, tagset_id }], ... }` |
    | `getTag`      | Get a tag by `id`.                            | `{ id, name, tagset_id }`                  |
    | `listTagsets` | List tag sets; filter by `tagset_ids`.        | `{ data: [{ id, name }], ... }`            |
    | `getTagset`   | Get a tag set by `id`.                        | `{ id, name }`                             |

    <Note>
      `Returns` shows the shape of the operation output. Mutations return the affected resource; deletes return HTTP 204 with an empty body.
    </Note>

    ## DSUL Examples

    **Log a time declaration:**

    ```yaml theme={null}
    - Gryzzly.createDeclaration:
        user_id: '{{user_id}}'
        task_id: '{{task_id}}'
        date: '{{run.date}}'
        duration: 7200
        description: Implementation review
      output: declaration
    ```

    **Create a project with a task:**

    ```yaml theme={null}
    - Gryzzly.createProject:
        name: Website Revamp
        start_at: 2026-01-06
        customer_id: '{{customer_id}}'
        visibility: private
        managers:
          - '{{manager_user_id}}'
      output: project
    - Gryzzly.createTask:
        project_id: '{{project.id}}'
        name: Design System
        start_at: 2026-01-06
        budget_type: time
        planned_duration: 80
      output: task
    ```

    **Read declarations for a payroll window:**

    ```yaml theme={null}
    - Gryzzly.listDeclarations:
        task_ids:
          - '{{task_id}}'
        user_ids:
          - '{{user_id}}'
        from: 2026-03-01
        to: 2026-03-31
      output: declarations
    ```

    **Invite a contributor:**

    ```yaml theme={null}
    - Gryzzly.inviteUser:
        email: new.hire@example.com
        role: contributor
        group_ids:
          - '{{group_id}}'
      output: invitation
    ```
  </Tab>
</Tabs>

***

## Error Handling

| HTTP Status | Error        | Solution                                                                                                 |
| ----------- | ------------ | -------------------------------------------------------------------------------------------------------- |
| 401         | Unauthorized | Verify the API key and `baseUrl` in the config app.                                                      |
| 403         | Forbidden    | The API key owner's Gryzzly role lacks permission for this resource.                                     |
| 404         | Not Found    | Verify the UUIDs for customer, project, task, user, etc.                                                 |
| 409         | Conflict     | Business rule rejected the write — e.g. setting `is_billable: true` on a project (see the billing trap). |
| 422         | Validation   | Check required fields and enum values (roles, visibility, budget type, etc.).                            |
| 429         | Rate Limited | Back off and retry with exponential delay.                                                               |
| 500         | Server error | Transient Gryzzly outage — retry shortly.                                                                |

### Common Issues

**"This agent is not authorized to use this connector"** — The calling agent is not in the allowlist. Open the configuration app → **Authorized agents** → tick this agent (or enable **Allow all agents**) and Save.

**"The calling agent could not be identified"** — The MCP capability *Scope* does not declare `agent_id`, so Agent Factory never injects the agent identity. Set the Scope to `context_id,agent_id,user_id` on the capability, then allow the agent in the config app.

**"Gryzzly is not configured for this workspace"** — No API key set. Open the configuration app and paste the Gryzzly API key (generated under **Administration > API Keys**) and, if needed, the base URL.

**`409 "can't handle billable project"`** — You tried to create or update a project with `is_billable: true`. Leave it false; billing modes are configured at the task level in the Gryzzly UI (`app.gryzzly.io`), not via the API.

**`contributors` rejected on a public project** — Set `visibility: private` or leave `contributors` empty.

## External Resources

<CardGroup cols={2}>
  <Card title="Gryzzly API" icon="book" href="https://api.gryzzly.io/v1/docs">
    Official Gryzzly v1 REST-RPC API documentation.
  </Card>

  <Card title="Tool Agents" icon="robot" href="/products/agent-factory/capabilities">
    Learn how Agent Factory agents consume MCP tools in Prisme.ai.
  </Card>
</CardGroup>
