service-omni-queue-members-assign

SkillProductivity

Binds agent users to a Salesforce queue using an omni claude skill flow, inserting only missing memberships.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the service-omni-queue-members-assign skill

About this skill

Use to bind agent users into a Salesforce Queue via GroupMember Data API POSTs, with SOQL-based idempotency (safe re-run, only inserts missing bindings). Binds either the generated demo agents (agent{1..N}.<suffix>@example.com) or an explicit list of real agents passed as usernames/User Ids. Trigge

What this skill tells your AI

The instructions your AI receives, as published by forcedotcom/sf-skills in skills/service-omni-queue-members-assign/SKILL.md and read by ahel’s review.

Bind N agent users into a Salesforce Queue via GroupMember Data API POSTs. Without queue membership, Omni-Channel routing sees an empty pool for the queue and never assigns work. Detection is SOQL-based (the same detect-then-POST shape as service-omni-queue-routing-config-deploy), so only missing memberships are created and the skill is safe to re-run. Agent users come from service-omni-agent-users-create, the queue from service-omni-queue-deploy, and the users' Omni permissions from service-omni-permission-set-assign.

Inputs

bash scripts/verify-and-bind.sh <org-alias> [queue-developer-name=CaseQueue] [count=3] [explicit-members-csv]
# demo agents (default):
bash scripts/verify-and-bind.sh myorg CaseQueue 3
# real agents by username/id:
bash scripts/verify-and-bind.sh myorg VoiceQueue "" "jdoe@acme.com,005XX000001abcd"
  • org-alias (required).
  • queue-developer-name (optional, default CaseQueue).
  • count (optional, default 3, range 1..10) — must match the agent user count; ignored in explicit mode.
  • explicit-members-csv (optional 4th positional, or MEMBER_USERNAMES_CSV / MEMBER_USER_IDS_CSV) — each token is a Username or a 15/18-char User Id; the count is derived from the list.

Preconditions and safety

  • Target org authenticated via sf CLI (My Domain URL), Service Cloud license, sf CLI ≥ 2.139.6.
  • The executing user has PermissionsModifyAllData (standard on System Administrator).
  • The agent users exist (service-omni-agent-users-create) and the queue exists (service-omni-queue-deploy); a missing user set or queue blocks with a pointer to the right skill (queues cannot be created via the Data API).
  • The three-way safe_to_write production guard applies — adding users to a production queue mis-routes real customer work, so it blocks with no override.

Run

verify-and-bind.sh runs the whole cycle:

  1. Compute safe_to_write; derive the 8-char org suffix.
  2. Resolve the queue Group.Id by DeveloperName + Type='Queue'; block if missing.
  3. Resolve the member set — generated mode queries User for agent{1..N}.<suffix>@example.com (block if any expected user is missing); explicit mode resolves each supplied token and requires every one to be an ACTIVE user.
  4. Query existing GroupMember for the queue; compute the users not yet bound.
  5. POST one GroupMember per missing user (individual POSTs, no allOrNone).
  6. Re-query to confirm final membership and emit the report.

Behavior

Two member sources, never mixed. The default generated pattern keeps the user-create → member-assign handoff deterministic; explicit mode is opt-in for real agents and takes over count derivation. In explicit mode, a token that does not resolve to an active user blocks the run — binding a typo'd or inactive user would silently under-populate the queue.

Idempotency and honesty. POSTs are individual so one failed binding (e.g. a race with another admin) never rolls back its successful siblings, and the skill re-queries after all POSTs — a 201 only means the write was accepted; a subsequent SOQL confirms the row is visible to the routing engine. The before snapshot includes members already present, even non-demo users added out-of-band, so the coordinator can see full membership state.

Non-destructive. Create-only; it never removes or reassigns existing members.

Output contract

A single JSON object with status ∈ bound | reused | partial | blocked, the resolved queue, org_suffix, member_source (generated_pattern | explicit), requested_count, a before snapshot, bound_this_run/bound_count, reused_count, an after snapshot, manual_actions, and blocking_issue.

  • bound — at least one new member created; final state matches the expected count.
  • reused — all expected users were already members; nothing POSTed.
  • partial — some POSTs failed; the re-query shows fewer members than requested (details in blocking_issue).
  • blocked — precondition failed (production org, missing queue, missing users, missing permissions).

bound_count + reused_count == requested_count unless partial; blocking_issue is non-null only for blocked/partial.

Limitations

  • Generated and explicit modes are mutually exclusive per run.
  • Create-only; removing or reassigning members is out of scope.
  • Does not create the queue or the users, and does not assign permission sets or presence configs.

References

FileWhen to read
references/api-notes.mdBefore the detect/bind cycle — GroupMember schema, the queue-vs-public-group distinction, why UserOrGroupId is polymorphic, and common POST failures
scripts/tests/test_queue_members_contracts.pyWhen validating changes — run python3 scripts/tests/test_queue_members_contracts.py from this skill directory

Signals

GitHub stars
1k
Forks
348
Last commit
Sep 2026

ahel review

  • K6low
    bundled executables the agent is told to run

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Item type
skill
Key
service-omni-queue-members-assign
Source
github.com/forcedotcom/sf-skills