Skip to content

This is a reference doc. It covers the OnboardingPlugin pipeline, request schema, idempotency guarantees, and trigger sources.


Overview

OnboardingPlugin (lib/plugins/onboarding.ts) runs the deterministic, idempotent side-effects of bringing a project online: registering its GitHub webhook, creating its Google Drive folder, and notifying downstream consumers.

Project registration itself lives in the GitHub-topic-driven project registry — the registry is compiled from every protoLabsAI repo tagged with the protoagent-plugin topic (plus an explicit base set) into a static projects.json served by the workstacean-projects nginx sidecar (see config-files and src/plugins/project-registry.ts). A repo is tagged with the protoagent-plugin topic before triggering onboarding here; this plugin does not create or persist a project record of its own. workstacean reads the canonical project list from the sidecar via the ProjectRegistry (exposed at GET /api/projects).


The pipeline

Steps run in sequence. Each step is individually idempotent — re-running the full pipeline for the same slug is safe.

#StepWhat it doesSkip condition
1validateChecks slug, title, and github are present; validates github is owner/repo format; rejects duplicate in-flight runs for the same slugMissing required fields or invalid format
2github_webhookRegisters a GitHub repo webhook for issues, issue_comment, pull_request, pull_request_review_comment events; lists existing webhooks first and skips if the target URL is already registeredNo GitHub auth (GITHUB_APP_ID or GITHUB_TOKEN), or WORKSTACEAN_PUBLIC_URL not set, or webhook already exists
3drive_folderCreates a Google Drive folder named after the project title, under the org root folder (drive.orgFolderId in workspace/google.yaml)Google credentials not set, google.yaml missing, or drive.orgFolderId empty
4bus_notifyPublishes message.inbound.onboard.complete with project metadata and per-step outcomes for downstream consumersNever skipped
5replySends a confirmation message (or error) to the inbound message's reply topicNo reply topic in the inbound message

Steps 2–3 are non-fatal: an error in one step is recorded in the step result and the pipeline continues. The plugin does not write any project file — it only performs the external side-effects and publishes the completion event.


OnboardRequest schema

Sent as the payload of a message.inbound.onboard bus message (or the JSON body of POST /api/onboard):

FieldTypeRequiredDefaultDescription
slugstringUnique project identifier, e.g. "protolabsai-myproject"
titlestringHuman-readable project name
githubstringRepository in "owner/repo" format
defaultBranchstring"main"Default git branch
teamstring"dev"Team assignment: "dev", "gtm", etc.
agentsstring[]["quinn"]Agent identifiers to associate
discordobject{}Discord channel IDs (general, updates, dev, alerts, releases)

These fields are echoed back on message.inbound.onboard.complete; the plugin does not persist them. Channel→agent bindings live in workspace/channels.yaml (ChannelRegistry), and project metadata lives in the GitHub-topic-driven project registry — neither is written by this plugin.


Idempotency guarantees

The pipeline is safe to re-run for the same project slug:

  1. Step 2 (github_webhook) lists existing webhooks before creating; skips if the target URL is already registered.
  2. Step 3 (drive_folder) is skipped entirely when Google credentials or the org folder ID are absent.
  3. In-flight guard — concurrent requests for the same slug are rejected with an error while the first run is in progress.

Inbound triggers

Bus topic (primary)

message.inbound.onboard

Any subscriber can publish to this topic to trigger onboarding. The payload must match the OnboardRequest schema above.

HTTP endpoint

POST /api/onboard
Content-Type: application/json

{
  "slug": "protolabsai-myproject",
  "title": "My Project",
  "github": "protoLabsAI/my-project"
}

The HTTP handler publishes to message.inbound.onboard and waits for the pipeline result on the reply topic.

Discord /onboard slash command

The Discord plugin routes slash commands to message.inbound.discord.slash.{interactionId} via the command config in workspace/discord.yaml. An /onboard command configured in discord.yaml can pass the project fields as options and publish to message.inbound.onboard.

GitHub org webhook: repository.created

When the GitHub org webhook is registered and a new repository is created under the org, lib/plugins/github.ts catches the repository + action: created event and publishes to message.inbound.onboard automatically. The payload uses the repository's full_name, name, owner.login, description, and visibility.


Outbound topics

TopicWhen publishedPayload highlights
message.inbound.onboard.completeAfter the pipeline runsslug, title, github, defaultBranch, team, agents, discord, driveFolderId, per-step status
{msg.reply.topic}After pipeline finishes (success or error)Full result with success, step, human-readable content

Environment variables

VariableRequired byDefaultPurpose
WORKSTACEAN_PUBLIC_URLgithub_webhookBase URL for webhook registration (e.g. https://ws.example.com)
GITHUB_APP_IDgithub_webhookGitHub App ID for auth (used by makeGitHubAuth)
GITHUB_APP_PRIVATE_KEYgithub_webhookGitHub App private key
GITHUB_TOKENgithub_webhookAlternative GitHub PAT for webhook registration
GITHUB_WEBHOOK_SECRETgithub_webhookOptional HMAC secret for GitHub webhooks
GOOGLE_CLIENT_IDdrive_folderGoogle OAuth client ID
GOOGLE_CLIENT_SECRETdrive_folderGoogle OAuth client secret
GOOGLE_REFRESH_TOKENdrive_folderGoogle OAuth refresh token

References

protoWorkstacean — a switchboard, not an agent.