-
Notifications
You must be signed in to change notification settings - Fork 8
Credential IDs should be human-readable slugs, not opaque UUIDs #84
Description
Problem
Credentials are currently identified by opaque UUIDs (e.g. 905372f3-5d9b-4d86-aa07-c0ac433fd3b5). This creates two concrete problems for agents:
1. X-Jentic-Credential header is impossible to use without a prior lookup
An agent that needs to disambiguate between a Gmail and a Calendar credential on googleapis.com must first call GET /toolkits/{id}/credentials, parse the response, find the right UUID, and carry it forward. There is no way to write a rule or instruction like "use the gmail credential" without that lookup step. Any generated tool call or workflow that hardcodes a credential reference will use an opaque UUID that is fragile, non-portable, and unreadable in logs.
2. X-Jentic-Credential-Used response header is opaque
When the broker returns X-Jentic-Credential-Used: 905372f3-5d9b-4d86-aa07-c0ac433fd3b5, neither a human reading logs nor an agent inspecting the response can immediately tell whether the right credential was used. A response header of X-Jentic-Credential-Used: work-gmail vs personal-gmail makes wrong-credential bugs obvious at a glance.
This is the same problem described in #34 — we fixed the mechanics of the override, but the usability problem (how does an agent know which slug to use?) is still open.
Proposed solution
Slugify credential labels as the primary public ID
When a credential is created with a label (e.g. "Work Gmail" or "GitHub Jentic PAT"), derive a stable slug from it: work-gmail, github-jentic-pat. This slug becomes the primary public identifier used in:
X-Jentic-Credentialrequest headerX-Jentic-Credential-Usedresponse headerGET /toolkits/{id}/credentialsresponse body (idfield)- Permission rules referencing a credential by ID
- Access request payloads (
credential_idfield)
The UUID is retained internally as the stable primary key and can also be accepted anywhere a slug is accepted (for backwards compatibility and in case of slug collisions), but it should not be the default thing shown to agents or humans.
Slug generation rules
- Lowercase, hyphens instead of spaces/underscores/punctuation
- Deduplicated within a toolkit (append
-2,-3etc. on collision) - Immutable once set — if the label changes, the slug does not (to avoid breaking existing references)
- Optionally allow the user to override the slug at creation time
Migration
- Existing credentials: derive slug from current label retroactively, or allow users to set slugs on existing credentials via PATCH
- Both UUID and slug should be accepted on all inbound API fields during transition
GET /credentialsshould return bothid(slug) anduuidfor transparency
Why this matters
We generally avoid opaque identifiers in user-facing APIs — a slug like work-gmail is self-documenting, survives copy-paste into prompts and rules, and makes debugging trivially easy. The pattern is well-established (GitHub repo slugs, Stripe customer IDs starting with cus_, etc.).
This is a prerequisite for agents being able to write robust, readable permission rules and credential references without a lookup round-trip every time.