Add HappyFox skill for help desk ticket management#197
Conversation
This skill enables interaction with the HappyFox help desk API for: - Creating and updating support tickets - Adding staff replies and private notes - Managing ticket status, priority, and assignee - Querying and filtering tickets - Working with custom fields - Moving tickets between categories Requires HAPPYFOX_API_KEY, HAPPYFOX_AUTH_CODE, and HAPPYFOX_SUBDOMAIN environment variables. Co-authored-by: openhands <openhands@all-hands.dev>
all-hands-bot
left a comment
There was a problem hiding this comment.
🟡 Acceptable - Well-structured skill with comprehensive documentation, but missing required marketplace entry.
Note: Review body kept brief per instructions. See inline comments for specific issues.
| @@ -0,0 +1,370 @@ | |||
| --- | |||
There was a problem hiding this comment.
🔴 Critical - Missing Marketplace Entry: This skill must be added to marketplaces/openhands-extensions.json or CI will fail.
According to AGENTS.md:
The test suite expects every directory under
skills/to be listed in a marketplace. If you add a new skill, update the appropriate marketplace file or CI will fail.
Add an entry alphabetically between gitlab and iterate with this structure:
{
"name": "happyfox",
"source": "./skills/happyfox",
"description": "Interact with HappyFox help desk - create tickets, add updates, manage ticket status, and query tickets using the HappyFox REST API.",
"category": "integration",
"keywords": [
"happyfox",
"help desk",
"support",
"ticket",
"api"
]
}|
|
||
| # HappyFox | ||
|
|
||
| <IMPORTANT> |
There was a problem hiding this comment.
🟢 Good Practice: Checking environment variables before use is the right approach. Clear, actionable guidance for users.
| - Auth Code: `$HAPPYFOX_AUTH_CODE` | ||
| - Subdomain: Your HappyFox account name (e.g., `acme` for `acme.happyfox.com`) | ||
|
|
||
| > **Note**: If your HappyFox account is hosted in EU, use `<subdomain>.happyfox.net` instead of `<subdomain>.happyfox.com` |
There was a problem hiding this comment.
🟡 Suggestion: Consider mentioning what determines EU vs US hosting. Users might not know which domain to use without checking their HappyFox admin panel.
Suggested addition:
> **Note**: If your HappyFox account is hosted in EU, use `<subdomain>.happyfox.net` instead of `<subdomain>.happyfox.com`. Check your HappyFox URL in your browser or contact your admin if unsure.|
|
||
| - `HAPPYFOX_API_KEY`: Your HappyFox API key | ||
| - `HAPPYFOX_AUTH_CODE`: Your HappyFox auth code | ||
| - `HAPPYFOX_SUBDOMAIN`: Your HappyFox account subdomain (e.g., `acme` for `acme.happyfox.com`) |
There was a problem hiding this comment.
🟢 Acceptable: The <IMPORTANT> block provides clear, practical guidance. The instruction to verify environment variables before operations follows good defensive programming practices.
- Add credential detection script that checks for HFOX_* or HAPPYFOX_* variables - HFOX prefix supports custom domains via HFOX_BASE_URL (full URL) - HAPPYFOX prefix uses HAPPYFOX_SUBDOMAIN for standard happyfox.com domains - Unified HF_* variables used in all API examples after detection - Updated README.md to document both configuration options Co-authored-by: openhands <openhands@all-hands.dev>
…havior notes - Add IMPORTANT warning that /staff_pvtnote/ is the ONLY way to create private notes - Clarify that /staff_update/ with visible_only_staff or private params does NOT create private notes - Document that update_customer: false only prevents email, reply is still visible in portal - Add note about attachment URL expiration (signed S3 URLs ~15 min) - Document message_type field: 'p' for private notes, null for regular updates - Add text field option for private notes (in addition to html) Co-authored-by: openhands <openhands@all-hands.dev>
ak684
left a comment
There was a problem hiding this comment.
overall looks good but let's get tests passing and I'd personally prefer less broad common word triggers (or maybe we leverage / command triggers instead to increase the intention threshold)
| - `help desk` | ||
| - `support ticket` |
There was a problem hiding this comment.
This is my first time reviewing these repo. Is it in fact that case that this skill directory gets pulled into every agent conversation on our SaaS / OHE instances by default? If so I think "help desk" and "support ticket" are too broad of triggers. Other customers may have help desk flows and be using Zendesk or Intencom and not HappyFox.
| @@ -0,0 +1,370 @@ | |||
| --- | |||
| - help desk | ||
| - support ticket |
Three documentation additions, all empirically verified against a live HappyFox v1.1 instance: 1. Write-safety: avoid duplicate writes HappyFox v1.1 has no edit/delete endpoint for individual updates or private notes — only whole-ticket deletion. There is no 'undo' for any write. Documents the right reflex on an ambiguous curl response (check exit code, GET-verify before any retry) and provides the canonical pre/post-state bash pattern. Lists the probed-and-confirmed dead-end delete/edit paths so future agents don't repeat the probes. 2. Endpoints that do NOT exist on v1.1 Quick reference table of integration / linked-object / linked-ticket paths that all return 404. Native integration metadata (e.g. the HappyFox<->Linear link) is not exposed via the API; cross-link enumeration must happen on the destination system. 3. Message Formatting: HTML Only, No Markdown Rendering matrix showing which HTML tags render (`<p>`, `<br>`, `<a href>`, `<strong>`, `<em>`, lists) vs which Markdown syntax appears as literal text (`##`, `**`, `[text](url)`, code spans). Cites HappyFox's 'Markdown Support while Adding Ticket Replies' release note to clarify that feature is a compose-box typing shortcut for human agents only — the API still treats `html` as HTML and `text` as plain text, never markdown. 4. Add Private Note (strengthened) Adds the `message.message_type` verification step: 'p' means private note, null means customer-visible. If a private-note POST ends up with `message_type: null`, internal content has leaked to the customer and there is no API to fix it. These rules were derived during a real cross-link backfill session on a live OpenHands HappyFox instance and prevented further duplicate writes after the first incident. Co-authored-by: openhands <openhands@all-hands.dev>
|
Pushed a9e6551 — three additions derived from a real cross-link backfill session on a live HappyFox v1.1 instance:
Cross-referenced by This comment was posted by an AI agent (OpenHands) on behalf of John-Mason Shackelford. |
The "Create a Ticket" section did not mention custom fields at all.
HappyFox v1.1 accepts ticket custom fields on create as form-field
keys named 't-cf-<id>' at the top level of the JSON payload, NOT
under a 'custom_fields' object. Discovered empirically while filing
a ticket on a live instance — the first attempt with 'custom_fields_1'
returned:
{"error":[{"field":"t-cf-1","errors":["This field is required"]}]}
The 422-style error response helpfully names the exact field key
the API expects, so the next attempt with 't-cf-1: <value>' works.
Adds:
- Optional-fields entry for 't-cf-<id>'.
- A worked POST example with both a choice (Product Type) and a text
(Conversation URL) custom field.
- The exact failure shape so future agents recognize it.
- Pointer to the "List Ticket Custom Fields" lookup section
(GET /ticket_custom_fields/) and to the per-ticket
custom_fields[] array as the two discovery paths.
Instance-specific custom-field IDs and choice tables stay in the
private 'openhands-happyfox' skill (extensions-private PR #2) — this
commit only documents the generic API convention.
Co-authored-by: openhands <openhands@all-hands.dev>
|
Pushed 597e227 — adds the The section previously didn't mention custom fields at all. Discovered the correct field-name shape empirically when a real ticket-create call returned: {"error":[{"field":"t-cf-1","errors":["This field is required"]}]}The 422 names the exact expected key, so the right reflex is to read the response. The commit adds a worked POST example with both a choice and a text custom field, the failure shape so future agents recognize it, and pointers to the existing Instance-specific custom-field IDs and choice tables remain in the private companion skill — only the API convention is documented here. This comment was posted by an AI agent (OpenHands) on behalf of John-Mason Shackelford. |
The skill previously documented attachment *reads* (signed S3 URLs in GET responses) but not attachment *uploads*. Add a section covering: - The docs-backed contract from /kb/article/1039-tickets-endpoint/ (field: 'attachments' plural, multipart/form-data, 25 MB combined cap, no file-type restrictions, UTF-8 encoding default) - Endpoints that accept attachments (POST /tickets/, /staff_update/, /staff_pvtnote/) plus the separate /ticket-inline-attachment/ for inline images embedded in the html field - A curl recipe (preferred) showing the multi-value form-field syntax - A Python stdlib (urllib) recipe as a fallback - A verification pattern that reads back .updates[-1].message.attachments - A caveat documenting an empirically-reproducible curl quirk: 'curl -F attachments=@/path/file' fails with '(26) Failed to open/read local data from file/application' on small readable files in some containerized environments (verified with curl 8.14.1). Documented as an empirical workaround so future agents fall through to Python immediately rather than wasting cycles retrying curl. Co-authored-by: openhands <openhands@all-hands.dev>
…-op audit entry Two empirically-verified additions to the 'Update Ticket Properties Only' section: 1. Custom fields can be updated on existing tickets via /staff_update/ using the same t-cf-<id> form-field convention as ticket creation. Text fields take raw strings; choice fields take the numeric choice id. 2. Every /staff_update/ POST creates an audit entry, even when the payload contains no message body and no tracked-change field (status, priority, assignee, tags, due_date). Property-only and custom-field-only writes therefore leave a 'message: null' row with all *_change fields null (custom_field_change is never populated by the API for custom-field writes). The row is invisible in the customer portal, sends no email, but does show in the staff timeline and bumps last_updated_at. Batch multiple property/custom-field writes into one call to avoid stacking no-op rows. Co-authored-by: openhands <openhands@all-hands.dev>
Summary
This PR adds a new skill for interacting with the HappyFox help desk API, enabling ticket creation and management operations.
Features
The HappyFox skill supports:
Required Environment Variables
HAPPYFOX_API_KEY: HappyFox API keyHAPPYFOX_AUTH_CODE: HappyFox auth codeHAPPYFOX_SUBDOMAIN: HappyFox account subdomain (e.g.,acmeforacme.happyfox.com)Documentation Sources
The skill is based on the official HappyFox API documentation:
Triggers
The skill is activated by:
happyfoxhelp desksupport ticketFiles Added
skills/happyfox/SKILL.md- Full skill documentation with API examplesskills/happyfox/README.md- Overview and quick referenceThis PR was created by an AI assistant (OpenHands) on behalf of the user.
@jpshackelford can click here to continue refining the PR