workspace/skills/halo-change-request/SKILL.md
Open a change request in HaloPSA / HaloITSM through a discover-preview-confirm-submit workflow, with the confirmed change ticket type cached in Memory. Use when raising a Halo change, opening a CR in Halo, submitting a change ticket, or asking NetClaw to file a change in HaloPSA.
npx skillsauth add automateyournetwork/netclaw halo-change-requestInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Open a change request in Halo through a strict discover -> preview -> confirm -> submit flow. Halo is HaloPSA / HaloITSM (the same product and the same REST API — HaloPSA is the MSP edition, HaloITSM the internal-IT edition). A "change request" in Halo is not a fixed object type: it is simply a ticket type ("Request Type") whose numeric id and custom fields are configured per organization — and an org often defines several change types (for example a customer-facing change and an internal change). This skill figures out which change is being raised, discovers the matching type, confirms it with a human, remembers it per category, learns its fields, and gates the single write behind explicit approval.
halo-mcp (NetClaw-authored, mcp-servers/halo-mcp/)python3 -u mcp-servers/halo-mcp/halo_mcp_server.py (stdio transport)HALO_CLIENT_ID / HALO_CLIENT_SECRET against HALO_BASE_URL (token from <base>/auth/token, resource API at <base>/api)fastmcp, httpx, python-dotenvhalo_create_change_request is the ONLY tool in the entire server that can mutate Halo, and it previews (no write) unless submit=true.This skill also uses the Memory MCP server (memory-mcp) to cache the confirmed change ticket type per Halo tenant.
| Tool | Parameters | What It Does |
|------|------------|--------------|
| halo_list_ticket_types | can_create_only?, customer?, showcounts? | Discover ticket types ("Request Types"). Use can_create_only=true to find the org's CHANGE type |
| halo_get_ticket_type | ticket_type | Authoritative field schema for a type — required/optional/visible field definitions |
| halo_list_fields | custom_only? | Master FieldInfo catalog (ids <-> names <-> dropdown option values) |
| halo_get_field | field | One field definition by numeric id, with its lookup values |
| halo_list_tickets | ticket_type?, customer?, asset_id?, status?, open_only?, search? | Find a sample existing change to copy field patterns from |
| halo_get_ticket | ticket (numeric id) | Read one populated ticket as a concrete example |
| halo_create_change_request | summary, details, ticket_type, customer?, site?, user?, asset?, custom_fields?, submit=false | THE ONLY WRITE. Previews the exact POST body unless submit=true |
| halo_list_clients | search? | Resolve a Halo Client name to its id (the customer param) |
| halo_list_sites | customer?, search? | Resolve a site within a client |
| halo_list_users | customer?, site_id?, search? | Resolve the requesting contact/user |
| memory_get_facts | entity, key? | Recall the tenant's change-type catalog (key="change_ticket_types") |
| memory_record_fact | entity, key, value, metadata? | Merge a confirmed change type ({id, name, category}) into the catalog |
| memory_record_decision | context, decision, rationale, ... | Log the human's ticket-type confirmation |
| memory_invalidate | fact_id, reason | Retire a cached ticket type that no longer resolves |
customer param (a client name or numeric id), which the server resolves to a client_id. When someone says "the client," they mean this.halo_create_change_request with submit=false performs NO HTTP write; it returns the exact array body that would be POSTed to /api/Tickets. The real POST happens only on a second call with submit=true.The full change-request flow, step by step. Do not skip steps (a) or (c).
An organization usually has more than one change type — most commonly a customer change (raised against a client) and an internal change (internal IT / infrastructure), and sometimes standard / normal / emergency splits. So first decide which change this is, then resolve the matching type. Never assume there is only one.
Decide the category. Infer from context: a change scoped to a specific
customer/client is a customer change; a change with no client (internal infra,
your own systems) is an internal change. If it is at all ambiguous, ASK the
operator — e.g. "Is this a customer change or an internal change?" Use a short
lowercase label for the category (customer, internal, emergency, ...).
Recall the tenant's change-type catalog:
memory_get_facts(entity="halo-<tenant>", key="change_ticket_types")
The value is a list of {"id":..., "name":..., "category":...} — the change types
already confirmed for this instance. <tenant> is from HALO_TENANT, or the host
of HALO_BASE_URL (e.g. halo-acme for acme.halopsa.com).
If the needed category is already in the catalog, validate it still resolves
with halo_get_ticket_type(ticket_type=<id>):
memory_invalidate the stale fact when you rewrite the catalog.If the category is missing (or was invalidated), discover:
halo_list_ticket_types(can_create_only=true)
This commonly returns several change-shaped types (e.g. "Change Request",
"Internal Change", "Emergency Change"). Present the candidates and ask the
operator which one is the <category> change — do NOT auto-pick when more than
one looks like a change, and do NOT collapse them into a single "the change type".
On confirmation, merge it into the catalog (add the new category; keep the others — do not overwrite the whole list with a single entry):
memory_record_fact(entity="halo-<tenant>", key="change_ticket_types",
value=<updated JSON list including {"id":<id>,"name":"<name>","category":"<category>"}>)
memory_record_decision(context="Halo change type for <tenant> / <category>",
decision="Use ticket type <id> (<name>) for <category> changes",
rationale="Operator-confirmed from halo_list_ticket_types(can_create_only=true)")
Carry the selected <id> into (b) and (c). If a single request genuinely spans both
a customer and an internal change, that is two change tickets — run the flow once
per category, confirming each.
Authoritative schema — which fields are required vs optional, and their dropdown values:
halo_get_ticket_type(ticket_type=<id>)
Use halo_list_fields / halo_get_field to resolve any custom FieldInfo ids <-> names <-> option values you need.
A concrete example — read a real, populated change to see how fields are actually filled:
halo_list_tickets(ticket_type=<id>) # find a recent one
halo_get_ticket(ticket=<sample id>) # inspect its summary/details/customfields
Cache field metadata alongside the type id (metadata={...}) if it helps future runs — but only the metadata, never any ticket's contents.
halo_list_clients, halo_list_sites, halo_list_users).halo_create_change_request(
summary="...", details="...", ticket_type="<id>",
customer="<client name or id>", site="...", user=<id>, asset="...",
custom_fields={<id-or-name>: <value>, ...},
submit=false)
body to the operator verbatim. It is the exact /api/Tickets payload.submit=true to perform the one real write.Log the decision and the created ticket id to the GAIT audit trail (see gait-session-tracking): the confirmed ticket type, the previewed body, the approval, and the resulting Halo ticket id.
| Skill | Integration |
|-------|-------------|
| gait-session-tracking | Mandatory. Record the ticket-type decision, the preview, the human approval, and the created ticket id in the GAIT audit trail |
| memory | Caches the per-category change-type catalog per tenant (entity="halo-<tenant>", key="change_ticket_types"); no credentials or ticket contents |
| halo-ticket-context | Read the created change and its action history afterward for follow-up |
| halo-asset-context | Review the affected asset and its open tickets before proposing the change |
| servicenow-change-workflow | Sibling gated-change pattern (STOP-until-confirmed) if the org also runs ServiceNow |
| Variable | Required | Description |
|----------|----------|-------------|
| HALO_BASE_URL | Yes | Halo host, e.g. https://<tenant>.halopsa.com |
| HALO_CLIENT_ID | Yes | OAuth2 client-credentials application id (Configuration > Integrations > Halo API) |
| HALO_CLIENT_SECRET | Yes | OAuth2 client secret |
| HALO_TENANT | Optional | Tenant identifier (also used to key Memory as halo-<tenant>) |
| HALO_SCOPE | Optional | OAuth2 scope (default all) |
| HALO_AUTH_URL | Optional | Override the auth-server URL for self-hosted layouts |
| HALO_VERIFY_SSL | Optional | true/false TLS verification (default true) |
| HALO_TIMEOUT | Optional | Per-request timeout in seconds (default 30) |
| HALO_PAGE_SIZE / HALO_MAX_PAGES | Optional | Pagination tuning (defaults 50 / 20) |
| HALO_RATE_LIMIT | Optional | Requests/minute cap (0 = disabled) |
halo_create_change_request. Every other Halo tool is read-only. Never attempt any other mutation through this server.submit=false), present the exact body, STOP, and only re-call with submit=true after the operator approves that preview (Constitution XIV).halo-<tenant>.halo_get_ticket_type, memory_invalidate it and re-discover.tools
Zoom meeting intelligence — correlates a live or referenced Zoom meeting discussion against NetClaw's historical meeting record (via the official Zoom Meetings MCP) and today's actual network state. Use when someone in a Zoom meeting references a past discussion or incident ('didn't we have this issue before?'), or asks to search prior meetings for a topic. Does not itself recognize live in-meeting questions — that happens automatically inside zoom-rtms-mcp's own extractor (spec 118) before this skill is ever invoked.
tools
Manage Lantronix out-of-band (OOB) infrastructure via Percepxion central management platform: device inventory, serial port inspection via SLC CLI, firmware compliance, config management, security auditing, and closed-loop incident remediation. Use during outages, maintenance windows, compliance cycles, and AI-assisted automation workflows.
tools
Federate your NetClaw with other NetClaw operators over the BGP mesh — exchange capability inventories and ask your claw what a peer can do. (US1; remote invocation and chat land in later phases.)
tools
Track token consumption, enforce session budgets, and display cost for every NetClaw interaction.