Rewrite BMS skill from bash to Python
This commit is contained in:
232
SKILL.md
232
SKILL.md
@@ -1,190 +1,146 @@
|
||||
# BMS Skill — Kaseya BMS Ticket Management
|
||||
|
||||
Manage service desk tickets in Kaseya BMS (Business Management Solution) via the BMS API v2.
|
||||
Python-based OpenClaw skill for Kaseya BMS ticket and note workflows.
|
||||
|
||||
## Scope
|
||||
|
||||
This skill focuses on:
|
||||
- ticket CRUD
|
||||
- ticket note CRUD
|
||||
- CRM account and account-scoped location lookup
|
||||
- template-assisted ticket creation
|
||||
- token handling with MFA support
|
||||
- account/location caching
|
||||
|
||||
## Configuration
|
||||
|
||||
Required environment variables (store in shell profile or a secrets manager):
|
||||
|
||||
```bash
|
||||
export BMS_TENANT="your-tenant-name" # Your BMS tenant/subdomain
|
||||
export BMS_USERNAME="user@example.com" # BMS login username
|
||||
export BMS_PASSWORD="yourpassword" # BMS login password
|
||||
# Or use client credentials (OAuth2):
|
||||
export BMS_CLIENT_ID="your-client-id"
|
||||
export BMS_CLIENT_SECRET="your-client-secret"
|
||||
export BMS_TENANT="your-tenant-name"
|
||||
export BMS_USERNAME="user@example.com"
|
||||
export BMS_PASSWORD="yourpassword"
|
||||
export BMS_MFA_CODE="123456" # when needed
|
||||
export BMS_API_BASE="https://api.bms.kaseya.com"
|
||||
export BMS_TOKEN_FILE="$HOME/.bms_token.json"
|
||||
export BMS_CACHE_FILE="$HOME/.cache/openclaw-bms/cache.json"
|
||||
```
|
||||
|
||||
Tokens are cached automatically at `~/.bms_token.json`.
|
||||
|
||||
## Commands
|
||||
|
||||
All commands route through `scripts/bms.sh`. Run without arguments for usage.
|
||||
|
||||
### Authentication
|
||||
Primary entrypoint:
|
||||
|
||||
```bash
|
||||
bms auth # Authenticate and cache token
|
||||
bms auth --status # Show token status / expiry
|
||||
bash scripts/bms.sh --help
|
||||
```
|
||||
|
||||
### Listing Tickets
|
||||
### Auth
|
||||
|
||||
```bash
|
||||
bms tickets list # All open tickets (paginated)
|
||||
bms tickets list --status "Open" # Filter by status name
|
||||
bms tickets list --assignee "John Smith" # Filter by assignee name
|
||||
bms tickets list --from 2024-01-01 --to 2024-01-31 # Filter by created date range
|
||||
bms tickets list --priority "High" # Filter by priority
|
||||
bms tickets list --queue "Support" # Filter by queue
|
||||
bms tickets list --account "Acme Corp" # Filter by account
|
||||
bms tickets list --page 2 --page-size 50 # Pagination
|
||||
bms tickets list --format json # Raw JSON output
|
||||
bms auth login
|
||||
bms auth refresh
|
||||
bms auth status
|
||||
```
|
||||
|
||||
### Getting a Ticket
|
||||
### Accounts and Locations
|
||||
|
||||
```bash
|
||||
bms tickets get <ticketId> # Get full ticket details
|
||||
bms tickets get <ticketId> --json # Raw JSON
|
||||
bms accounts
|
||||
bms accounts --refresh
|
||||
bms locations --account 12345
|
||||
bms locations --account 12345 --refresh
|
||||
```
|
||||
|
||||
### Creating Tickets
|
||||
Important:
|
||||
- locations are tied to accounts
|
||||
- the same location name can exist under multiple accounts with different IDs
|
||||
- always resolve location IDs in the context of a specific account
|
||||
|
||||
### Tickets
|
||||
|
||||
```bash
|
||||
bms tickets create \
|
||||
--title "Server is down" \
|
||||
--details "The main server stopped responding at 2pm" \
|
||||
--account-id 123 \
|
||||
--location-id 456 \
|
||||
--status-id 1 \
|
||||
--priority-id 2 \
|
||||
--type-id 1 \
|
||||
--source-id 1 \
|
||||
--assignee-id 789
|
||||
bms tickets list --status Open --assignee "Jane Doe"
|
||||
bms tickets get 12345
|
||||
bms tickets create --title "test" --details "Test" --account-id 1 --location-id 2 --status-id 3 --priority-id 4 --type-id 5 --source-id 6 --queue-id 7
|
||||
bms tickets create --template-id 9 --title "Override title" --account-id 1 --location-id 2 --queue-id 7
|
||||
bms tickets patch 12345 /StatusId 6
|
||||
bms tickets assign 12345 --details "Routing" --type-id 1 --status-id 6 --queue-id 7
|
||||
bms tickets delete 12345
|
||||
```
|
||||
|
||||
Create from a **template** (pre-fills fields; CLI overrides take precedence):
|
||||
Features:
|
||||
- `--open-date` supported for ticket creation
|
||||
- template-based creation merges template defaults with explicit overrides
|
||||
- create validation requires all required fields plus either `queue-id` or `assignee-id`
|
||||
- create path makes one API call only and validates response semantics before reporting success
|
||||
|
||||
### Notes
|
||||
|
||||
```bash
|
||||
bms tickets create --template-id 7 --account-id 123 --location-id 456
|
||||
# Fields from template 7 are used; only account/location are overridden.
|
||||
# Any required field still missing triggers an interactive prompt.
|
||||
bms notes list 12345
|
||||
bms notes add 12345 --message "Investigating" --note-date 2026-04-07T12:00:00+00:00
|
||||
bms notes update 12345 999 --message "Corrected note" --note-date 2026-04-07T13:00:00+00:00
|
||||
bms notes delete 12345 999
|
||||
```
|
||||
|
||||
Or use fully interactive mode (prompts for all required fields):
|
||||
|
||||
```bash
|
||||
bms tickets create --interactive
|
||||
```
|
||||
|
||||
### Updating Tickets
|
||||
|
||||
```bash
|
||||
bms tickets update <ticketId> --status-id 3 # Change status
|
||||
bms tickets update <ticketId> --assignee-id 789 # Reassign
|
||||
bms tickets update <ticketId> --priority-id 1 # Change priority
|
||||
bms tickets update <ticketId> --title "New title" # Update title
|
||||
```
|
||||
|
||||
### Adding Notes
|
||||
|
||||
```bash
|
||||
bms tickets note <ticketId> --message "Called client, investigating"
|
||||
bms tickets note <ticketId> --message "Internal update" --internal
|
||||
bms tickets note <ticketId> --message "Resolved via restart" --status-id 5
|
||||
```
|
||||
|
||||
### Assigning Tickets
|
||||
|
||||
```bash
|
||||
bms tickets assign <ticketId> --assignee-id 789 --note "Routing to tier 2"
|
||||
bms tickets assign <ticketId> --queue-id 3
|
||||
```
|
||||
|
||||
### Resolving Tickets
|
||||
|
||||
```bash
|
||||
bms tickets resolve <ticketId> --comment "Replaced failed drive, server is back online"
|
||||
bms tickets resolve <ticketId> --comment "Fixed" --status-id 6 --publish-kb
|
||||
```
|
||||
|
||||
### Deleting Tickets
|
||||
|
||||
```bash
|
||||
bms tickets delete <ticketId> # Delete single ticket
|
||||
bms tickets delete 123 456 789 # Delete multiple tickets
|
||||
```
|
||||
|
||||
### Lookup Tables (for getting valid IDs)
|
||||
|
||||
```bash
|
||||
bms lookup statuses # List all ticket statuses with IDs
|
||||
bms lookup priorities # List all priorities with IDs
|
||||
bms lookup queues # List all queues with IDs
|
||||
bms lookup issue-types # List all issue types
|
||||
bms lookup assignees # List all assignees/technicians
|
||||
bms accounts # List CRM accounts (Id, Name, Code)
|
||||
bms locations --account 123 # List CRM locations for account 123
|
||||
bms lookup ticket-types # Not exposed in public BMS v2 Swagger for all tenants
|
||||
bms lookup sources # Not exposed in public BMS v2 Swagger for all tenants
|
||||
```
|
||||
Features:
|
||||
- custom note dates supported for create and update
|
||||
- note CRUD exposed directly in the Python CLI
|
||||
|
||||
### Templates
|
||||
|
||||
Browse pre-defined ticket, note, and timelog templates configured in BMS.
|
||||
|
||||
```bash
|
||||
bms templates tickets list # List all ticket templates (Id, Name, QueueId, PriorityId, etc.)
|
||||
bms templates tickets get <id> # Inspect a specific ticket template (raw JSON)
|
||||
bms templates notes list # List all note templates
|
||||
bms templates timelogs list # List all timelog templates
|
||||
|
||||
# Add --format json to any list command for raw JSON output
|
||||
bms templates tickets list --format json
|
||||
bms templates tickets list
|
||||
bms templates tickets get 9
|
||||
bms templates notes list
|
||||
bms templates timelogs list
|
||||
```
|
||||
|
||||
## Template-Based Ticket Creation
|
||||
Templates are read-only.
|
||||
|
||||
`bms tickets create --template-id <N>` does the following:
|
||||
## Endpoints used
|
||||
|
||||
1. Fetches `GET /v2/servicedesk/templates/tickets/{templateId}` to retrieve template defaults.
|
||||
2. Merges them with any CLI overrides you provide (`--title`, `--description`, `--account-id`, `--location-id`, `--status-id`, `--priority-id`, `--type-id`, `--source-id`, `--assignee-id`, `--queue-id`, `--due-date`, `--contact-id`). CLI values always win.
|
||||
3. Prompts interactively (via stdin) for any required field still missing after the merge.
|
||||
4. Posts the final payload to `POST /v2/servicedesk/tickets`.
|
||||
Auth:
|
||||
- `POST /v2/security/authenticate`
|
||||
- `POST /v2/security/refreshtoken`
|
||||
|
||||
Use `bms templates tickets list` to see available template IDs before creating.
|
||||
CRM lookup:
|
||||
- `GET /v2/crm/accounts/lookup`
|
||||
- `GET /v2/crm/accounts/{accountId}/locations/lookup`
|
||||
|
||||
## Notes / Quirks
|
||||
Tickets:
|
||||
- `POST /v2/servicedesk/tickets/search`
|
||||
- `GET /v2/servicedesk/tickets/{ticketId}`
|
||||
- `POST /v2/servicedesk/tickets`
|
||||
- `PATCH /v2/servicedesk/tickets/{ticketId}`
|
||||
- `DELETE /v2/servicedesk/tickets/{ticketId}`
|
||||
- `POST /v2/servicedesk/tickets/{ticketId}/assignticket`
|
||||
|
||||
- **Auth**: BMS uses JWT Bearer tokens obtained via `POST /v2/security/authenticate` with `GrantType=password`. Tokens expire; the skill auto-refreshes using `POST /v2/security/refreshtoken`.
|
||||
- **Required fields for ticket creation**: Title, Details, AccountId, LocationId, StatusId, PriorityId, TypeId, SourceId, OpenDate — all are required by the API schema.
|
||||
- **IDs not names**: The API uses integer IDs for status, priority, type, etc. Use `bms lookup`, `bms accounts`, and `bms locations` to find the right IDs for your tenant.
|
||||
- **Search vs GET list**: For filtered searches, `POST /v2/servicedesk/tickets/search` (with body) is more flexible than `GET /v2/servicedesk/tickets` (with query params); this skill uses the POST search by default.
|
||||
- **Pagination**: Default page size is 25. Use `--page-size` (max appears to be 100) and `--page` for large result sets.
|
||||
- **Date format**: Dates should be ISO 8601 strings, e.g. `2024-01-15T00:00:00`.
|
||||
- **Note TypeId**: Required when posting notes. The public BMS v2 Swagger does not clearly expose a generic note-type lookup endpoint for all tenants, so you may need tenant-specific documentation or known values.
|
||||
- **Rate limits**: Not documented in the Swagger spec. Treat as standard REST API — avoid tight loops; add a small sleep between bulk operations.
|
||||
Notes:
|
||||
- `GET /v2/servicedesk/tickets/{ticketId}/notes`
|
||||
- `POST /v2/servicedesk/tickets/{ticketId}/notes`
|
||||
- `PUT /v2/servicedesk/tickets/{ticketId}/notes/{noteId}`
|
||||
- `DELETE /v2/servicedesk/tickets/{ticketId}/notes/{noteId}`
|
||||
|
||||
## Note Type IDs (Grand Portage Tenant)
|
||||
Templates:
|
||||
- `GET /v2/servicedesk/templates/tickets/lookup`
|
||||
- `GET /v2/servicedesk/templates/tickets/{templateId}`
|
||||
- `GET /v2/servicedesk/templates/notes/lookup`
|
||||
- `GET /v2/servicedesk/templates/timelogs/lookup`
|
||||
|
||||
Based on testing for Grand Portage, the following note type IDs are valid:
|
||||
## Note Type IDs (Grand Portage tenant)
|
||||
|
||||
Known working values from tenant testing:
|
||||
- `0` — Email Sent
|
||||
- `1` — Email Received
|
||||
- `2` — General Notes
|
||||
- `3` — Phone Call
|
||||
- `4` — Resolution
|
||||
|
||||
Note: These are tenant-specific and may differ in other BMS deployments. The public Swagger does not fully expose note type lookups.
|
||||
These are tenant-specific and may differ elsewhere.
|
||||
|
||||
## References
|
||||
## Implementation notes
|
||||
|
||||
- [BMS API Swagger UI](https://api.bms.kaseya.com/swagger/index.html)
|
||||
- [BMS API Swagger JSON](https://api.bms.kaseya.com/swagger/v2/swagger.json)
|
||||
- `references/key-schemas.md` — TicketInputDto, filter, and note schemas
|
||||
- `scripts/bms.sh` — Main CLI entrypoint
|
||||
- `scripts/bms-auth.sh` — Auth and token management
|
||||
- `scripts/bms-tickets.sh` — Ticket CRUD operations (includes `--template-id` support)
|
||||
- `scripts/bms-lookup.sh` — Lookup table helpers
|
||||
- `scripts/bms-templates.sh` — Template listing commands (tickets, notes, timelogs)
|
||||
- Python standard library only
|
||||
- shell scripts retained as compatibility wrappers around the Python CLI
|
||||
- cached lookups reduce repeated account/location API calls
|
||||
- account/location cache TTL is 24 hours by default
|
||||
- designed for Daniel’s direct use and BMS operator workflows
|
||||
|
||||
Reference in New Issue
Block a user