Technical docs

Staff

Overview

Support reference for the Staff area:

  • `/staff`
  • `/staff/ai/[employee_id]`
  • `/staff/user/[user_id]`

What users see

  • Main tabs: `Staff` and `Invites`.
  • Trash view is reached from `View Deleted` and is labeled `Pending Deletion`.
  • The invite dialog also opens from `?invite=true`.
  • Primary actions on the active Staff view:
  • `Invite Member`
  • `Add AI Teammate`
  • Empty state buttons:
  • `Invite Member`
  • `Add AI`

Staff tab

  • Header title: `Staff Directory`.
  • Description: `Manage your team members and AI Teammates in one place`.
  • Current table filters:
  • `Type`: `Team Member`, `AI Teammate`
  • `Status`: `Active`, `Pending`, `Inactive`
  • `Added`
  • `Updated` or `Deleted` in trash view
  • `Role`
  • `AI Skill`
  • Current table columns can include:
  • `LLM` for AI teammates
  • The `LLM` cell shows the resolved model display name when Alloy has one, otherwise the raw model id.
  • Current behavior:
  • The staff API currently returns the full list without server pagination, server filtering, or server search.
  • Search, pagination, date filters, role filters, and skill filters are handled in the frontend.
  • Human rows come from accepted organization memberships, not from pending invites.
  • Trash view is AI-teammates only.
  • Per-user Ally rows show a `Personal` badge in the name cell.
  • Row actions:
  • AI teammates: `Chat`
  • All rows: click-through to the detail page
  • Human teammates: no inline action button in the list
  • Bulk actions:
  • Active view: `Delete`
  • Trash view: `Restore`
  • Selection rules:
  • active-view human owners cannot be bulk-selected
  • active-view system AI teammates cannot be bulk-selected
  • trash-view selection is AI-only

Invites tab

  • Header title: `Pending Invites`.
  • Description: `Track and manage pending organization invitations`.
  • The invite dialog supports two delivery methods:
  • send by email
  • generate a shareable invite link
  • Both delivery methods create the same backend invite record through `POST /api/organizations/{orgId}/invites/`.
  • The dialog's `Administrator` option maps to backend invite role `admin`.
  • The free-text `Position` field is currently UI-only and is not persisted by the backend invite model.
  • Current filters:
  • `Status`: `Pending`, `Accepted`, `Cancelled`, `Expired`
  • `Role`: `Admin`, `Member`
  • `Added`
  • `Updated`
  • Row actions:
  • pending email invites: `Resend`, `Cancel`, `Copy invite link`
  • pending link invites: `Cancel`, `Copy invite link`
  • accepted, cancelled, and expired rows are read-only
  • Invites use server pagination, but filtering and status presentation are handled in the frontend.
  • The frontend treats a pending invite whose `expires_at` is in the past as `Expired` for display.

AI teammate detail

  • Create route: `/staff/ai/new`.
  • Create mode initially exposes only the `Rules` tab; the full tab set appears after the teammate is created.
  • Tabs:
  • `Rules`
  • `Skills`
  • `Storage`
  • `Connectors`
  • `PATs`
  • `Telegram`
  • `MS Teams`
  • `Slack`
  • `Logs`
  • `Reports`
  • `Jobs`
  • `Schedulers`
  • `API` only when channel is `API`
  • When the tab strip is too narrow, hidden tabs move into the `Tabs` overflow menu. The overflow menu can select hidden tabs, change which tabs stay visible, and reorder tabs through `Reorder {name}` drag handles. Tab tooltips use the current tab descriptions, including `Review activity and execution history` for Logs, `Review performance and usage reports` for Reports, and `Schedule recurring and one-off runs` for Schedulers.
  • Ally is a special case:
  • their detail page hides `Storage`
  • their detail page hides `API`
  • a personal Ally is auto-created for each user the first time the employee list or staff list is accessed, so every user always has an Ally without manual setup
  • the current user's personal Ally is available in shared internal-chat target strips and history
  • personal Ally employees remain excluded from Cowork teammate selection, `@` mention catalogs, skills builder selectors, Staff table teammate choices, and system settings dropdowns for global Ally and Onboarding teammate selection
  • Channel choices in the header:
  • `Not selected`
  • `Web Chat`
  • `API`
  • `Web Chat` shows a copy action for the chat widget snippet in the header.
  • `API` uses a dedicated tab with:
  • `API Endpoint`
  • request examples and built-in request tester
  • API request log filtered from workflow runs
  • Jobs and schedulers are documented in jobs-and-schedulers.md. The Schedulers tab uses a mixed recurring/one-off list, dashboard metrics, and create cards for `Schedule recurring` and `One-off run`.
  • Connectors tab lets users enable or disable org MCP servers for that teammate. The tab description is `Connected systems and services`.
  • The same Connectors tab also manages OAuth service connections for that specific teammate.
  • For connected OAuth services, the tab can show:
  • status badge `Valid`, `Invalid`, or `Unknown`
  • `Connected by {user}`
  • connected account identifier when available
  • OAuth connector checkboxes stay disabled until the matching service is connected for that teammate.
  • PATs tab lets users create tokens that let external AI agents act as that teammate.
  • Telegram tab lets users:
  • connect a Telegram bot by pasting a BotFather token
  • disconnect the linked bot
  • reconnect the webhook when the bot is linked but webhook delivery is not active
  • Telegram tab states:
  • unlinked: `No Telegram bot is linked to this AI Teammate yet. Connect a bot to receive messages from Telegram.`
  • linked + active webhook: `Connected` badge plus webhook success notice
  • linked + missing webhook: warning notice plus `Reconnect webhook`
  • MS Teams tab lets users:
  • connect a Microsoft Teams bot by entering Azure Bot app credentials
  • disconnect the linked Teams bot
  • copy the current `Messaging endpoint (set this in your Azure Bot)` value
  • download the sideloadable Teams app package as `.zip`
  • Full setup procedure: `tech docs/references/microsoft-teams-ai-teammate.md`.
  • MS Teams tab always shows the current messaging endpoint when the backend provides one, even before the bot is connected.
  • MS Teams tab currently has two nested views:
  • `Contacts`
  • `Channels`
  • `Contacts` shows the per-contact approval list for personal Teams chats.
  • Personal Teams bot replies are gated by contact approval state:
  • `Approved`
  • `Not approved`
  • The contact approval switch lets users allow or block AI replies for each listed Teams contact.
  • `Channels` shows Teams channels and group chats the bot has already seen.
  • Channel rows currently show:
  • display name from `channel_name`, or fallback to raw `ms_teams_channel_id`
  • status badge `Enabled` or `Disabled`
  • a toggle for enabling or disabling AI replies in that channel or group
  • Newly discovered Teams channels are created disabled by default and only appear after the bot has seen a message there.
  • Slack tab lets users:
  • connect a Slack bot by entering Bot User OAuth Token and Signing Secret
  • disconnect the linked bot
  • copy a generated Slack app manifest JSON for quick app setup
  • copy the `Events Request URL` from the `Troubleshooting` accordion when Slack URL verification needs checking
  • Full setup procedure: `tech docs/references/slack-ai-teammate.md`.
  • Slack tab states:
  • unlinked: `No Slack bot is linked to this AI Teammate yet. Connect a dedicated Slack app to receive messages from Slack.`
  • linked: `Connected` badge with bot app name and bot user ID
  • Slack tab shows a `Quick setup with a Slack app manifest` card before connection. The manifest is generated by the backend and pre-fills the Slack app name, scopes, events, App Home direct-message settings, and Events Request URL.
  • Slack tab shows a `ChannelChatsList` for managing per-channel enable/disable state, same pattern as Telegram and MS Teams tabs.
  • Slack app setup details live in the Slack reference instead of this Staff-area overview.
  • Storage tab shows only the folders explicitly shared with that teammate; it no longer expands every file inside those folders into the table.
  • The Storage table is centered on access-management metadata: shared folder name, location, current teammate access, grantor, and grant date.
  • Storage table filters include created, modified, granted, team, and grantor.
  • Folder row actions are `Open`, `Share`, and `Delete`.
  • The empty state for AI teammate Storage still links back to `/storage`.
  • Employee-backed search/list endpoints filter per-user Ally records so a signed-in user only sees their own Ally.
  • Updating a per-user Ally keeps the name fixed as `Ally`; editable fields are the assistant settings such as description, role, instructions, model, tools, and voice configuration.
  • In the AI teammate model picker, Codex models are disabled when `GET /api/init/models` returns `is_connected: false` for them. Disabled Codex models show a lock icon with accessibility label `Codex is not connected`.
  • When a provider group contains unavailable Codex models, org admins see a `Connect` link to `/org-settings/api-keys`; non-admin users see `Admin required`.
  • System AI teammates cannot be deleted from the active Staff list, bulk delete, or the AI teammate detail page.
  • AI teammate create and update paths now snapshot teammate state into the shared backend `entity_versions` store.
  • The stored entity type for AI teammate versions is `ai_employee`.
  • Restore support is confirmed in backend code through the shared entity-version restore route.
  • This doc does not claim a dedicated AI teammate version-history UI because that was not confirmed in the current frontend source.

Human teammate detail

  • Back action: `Back`.
  • The route reads accepted organization users via `GET /api/organizations/{orgId}/users/{user_id}`.
  • Pending invitations stay in the `Invites` tab and do not become human Staff rows.
  • Overflow menu includes:
  • `Open in new tab`
  • `Remove` for non-owner rows only
  • The page shows email, phone, location, joined date, and invited date when available.

API and realtime

  • Staff list:
  • `GET /api/organizations/{orgId}/staff`
  • `GET /api/organizations/{orgId}/staff/deleted`
  • Humans:
  • `GET /api/organizations/{orgId}/users`
  • `GET /api/organizations/{orgId}/users/{user_id}`
  • `PUT /api/organizations/{orgId}/users/{user_id}/role`
  • `DELETE /api/organizations/{orgId}/users/{user_id}`
  • `POST /api/organizations/{orgId}/users/bulk-delete`
  • `POST /api/organizations/{orgId}/users/bulk-restore`
  • Invites:
  • `POST /api/organizations/{orgId}/invites/`
  • `GET /api/organizations/{orgId}/invites/`
  • `DELETE /api/organizations/{orgId}/invites/{invite_id}/`
  • `POST /api/organizations/{orgId}/invites/{invite_id}/resend`
  • public acceptance flow: `/api/invites/{code}` and `/api/invites/{code}/accept`
  • AI teammates:
  • `GET /api/organizations/{orgId}/employees/`
  • `POST /api/organizations/{orgId}/employees/`
  • `GET /api/organizations/{orgId}/employees/{employee_id}`
  • `PUT /api/organizations/{orgId}/employees/{employee_id}`
  • `DELETE /api/organizations/{orgId}/employees/{employee_id}`
  • `POST /api/organizations/{orgId}/employees/bulk-delete`
  • `POST /api/organizations/{orgId}/employees/bulk-restore`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/external-urls`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/telegram`
  • `POST /api/organizations/{orgId}/employees/{employee_id}/telegram`
  • `DELETE /api/organizations/{orgId}/employees/{employee_id}/telegram`
  • `PUT /api/organizations/{orgId}/employees/{employee_id}/telegram/webhook`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/msteams`
  • `POST /api/organizations/{orgId}/employees/{employee_id}/msteams`
  • `DELETE /api/organizations/{orgId}/employees/{employee_id}/msteams`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/msteams/contacts`
  • `POST /api/organizations/{orgId}/employees/{employee_id}/msteams/contacts/{contact_id}`
  • `DELETE /api/organizations/{orgId}/employees/{employee_id}/msteams/contacts/{contact_id}`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/msteams/channels`
  • `PUT /api/organizations/{orgId}/employees/{employee_id}/msteams/channels/{channel_id}/status`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/msteams/package`
  • `GET /api/organizations/{orgId}/employees/{employee_id}/slack/manifest`
  • `GET /api/organizations/{orgId}/entity-versions/ai_employee/{employee_id}?limit=<n>&before_version=<n>`
  • `POST /api/organizations/{orgId}/entity-versions/{entity_version_id}/restore`
  • Logs and MCPs:
  • `GET /api/organizations/{orgId}/workflows/runs/`
  • `GET /api/organizations/{orgId}/mcps`
  • `GET /api/organizations/{orgId}/mcps?employee_id={employee_id}`
  • `POST /api/organizations/{orgId}/mcps/{mcp_id}/employee/{employee_id}`
  • `DELETE /api/organizations/{orgId}/mcps/{mcp_id}/employee/{employee_id}`
  • Jobs and schedulers APIs are documented in jobs-and-schedulers.md.
  • WebSocket events used by Staff/Invites:
  • `organization.staff_user_added`
  • `organization.staff_user_removed`
  • `ai_employee.created`
  • `ai_employee.updated`
  • `ai_employee.deleted`
  • `staff_employee.created`
  • `staff_employee.updated`
  • `staff_employee.deleted`
  • `organization_invite.created`
  • `organization_invite.updated`
  • `ai_employee_ms_teams_channel.created`
  • `ai_employee_ms_teams_channel.updated`

Permission notes

  • Staff and invite actions are organization-scoped and authorized by backend checks.
  • Human removal and human bulk delete/restore are admin-or-owner only on the backend.
  • Human role changes are owner-only on the backend.
  • The current trash UI only surfaces deleted AI teammates even though backend user restore endpoints exist.

Start building your AI team