Michael Suchacz adcce66826 feat: load organization skills in chats (#30613)
## Stack

Closes
[CODAGT-1341](https://linear.app/codercom/issue/CODAGT-1341/support-organization-level-skills-in-coder-agents).
This stack adds organization skills to Coder Agents: admins publish a
skill once per organization, share it with groups or members, and chats
in that organization load it next to personal and workspace skills. It
replaces the 21-PR draft stack #30584 to #30604 with five PRs, bottom to
top:

1. #30609 data model: one migration, queries, RBAC and dbauthz
2. #30610 organization skill API routes and the scope-neutral SDK
3. #30611 sharing ACL routes
4. #30612 settings UI: shared skills table, admin page, member section
5. **#30613** chats: chatd loading, `/` menu, docs (this PR)

## What changes

This PR makes chats use organization skills: chatd adds the skills
shared with the chat owner in the chat's organization to the skill
index, `read_skill` loads them, the `/` menu offers them, and the docs
describe the feature.

**chatd** (`coderd/x/skills`, `coderd/x/chatd`):

- New source `skills.SourceOrganization` (`"org"`).
`MergeSkills(personal, organization, workspace)` sorts by name, then
source. A name in one source keeps its bare alias; a name in more than
one source gets a qualified alias in every source that has it
(`personal/<name>`, `org/<name>`, `workspace/<name>`), so no source
overrides another. `Lookup` returns `ErrSkillAmbiguous` for a bare name
that matches several sources.
- **Authorization (please review closely):** each turn, chatd reads
organization skill metadata and bodies as the chat owner's real RBAC
subject with their roles and groups (`chatOwnerSubject`), never as the
chatd system actor, so per-skill ACLs apply. Disabled skills are
skipped. A skill that is deleted, disabled, or no longer shared by the
time `read_skill` runs is reported as not found. If the owner subject or
the metadata can't be loaded, turn preparation fails with the error, as
main now does for personal skills (#30492), instead of running the turn
without organization skills.
- `read_skill` loads personal and organization bodies through one
`LoadStoredSkillBody` callback. An index description longer than 1,024
runes, the Agent Skills specification limit
(`maxSkillIndexDescriptionRunes`), is cut to 1,023 runes plus an
ellipsis so it stays within the limit; `read_skill` still returns the
full skill.
- Parse and lookup errors keep `%w` last on purpose: with `xerrors`, a
`%w` that isn't last repeats the cause, so main's detail read "skill is
too large: got N bytes, maximum is 65536 bytes: skill is too large".
This stack returns the cause once (ThomasK33 asked about the order in
review).

**`/` menu** (`site/src/pages/AgentsPage`): the chat page fetches the
chat organization's enabled skills (`organizationSkills(...)` from
#30612's queries) next to personal ones. `utils/skillAliases.ts`
(`resolveSkillTriggers`) follows `MergeSkills`: a personal or
organization trigger is bare unless its name is in more than one source,
then it becomes `/personal/<name>` or `/org/<name>`. While any list is
unknown every trigger is qualified, because a qualified alias always
resolves; workspace triggers are always qualified. Built-in `/clear` and
`/compact` stay pending until every skill list is known, and a list with
no data counts as unknown even after an error, so a failed fetch can't
make a built-in run in place of a same-named skill. Disabled skills
never shadow a built-in.

**Docs:** `docs/ai-coder/agents/extending-agents.md` gains two sections,
Organization skills (manage them, control who can use one, find the ones
you can use) and How chats load stored skills (turning a skill on or
off, skills with the same name). The admin page's organization picker
shows only for a user who can view more than one organization's skills.
The member "From your organizations" section shows one organization at a
time with its own picker, starts on the default organization, and has
Export all for the selected organization. The Enabled column is a switch
for editors and a check or X otherwise. The settings table in
`platform-controls/organizations.md` gains rows for organization and
personal skills.

## Commits

The first commit reproduces the reviewed chatd code from the old stack;
the site and docs commits reapply the old layers on #30612's queries,
and the rest are labeled trims or fixes.

- `aa634eec94a` feat(coderd/x): load organization skills in chats.
Reproduction of the old skill sources and chatd layers (old head
`a1047f4986`).
- `97945db4e86` test(coderd/x/skills): make `TestMergeSkills` (6 cases)
and `TestLookup` (8 cases) table-driven; coverage is 100% before and
after, with the same blocks.
- `dde61cc5fe2` test(coderd/x/chatd): drop skill tests duplicated by the
organization skills integration test
`TestOrganizationSkillsFollowChatOwnerAccess`; the covered block set of
the touched code is identical (348 of 506 blocks).
- `aad14b2dd05` feat(site/src/pages/AgentsPage): show organization
skills in the slash menu. The old alias helper and slash menu layers,
applied cleanly on #30612's queries.
- `712e272e140` test(site/src/pages/AgentsPage): trim duplicated slash
menu tests and stories. Deletes `AgentChatPage.test.tsx` (177 lines; its
assertions live in `submitChatTurn.test.ts` and
`ChatMessageInput.test.tsx`), two duplicate `ChatMessageInput` cases,
six of 17 `SkillsTriggerMenu` stories, and one disabled-skill fixture
row from a `ChatMessageInput` story.
- `232535e1011` docs(docs/ai-coder/agents): document organization
skills. From the old docs layer, with the View line updated for #30612's
read-only dialog and Download.
- `62dbbd2dfd3` refactor(site/src/pages/AgentsPage): address frontend
review on the slash menu.
- `7349eac4389` Merge the updated settings-ui layer into chats. Brings
in the #30610 and #30612 fixes; the merge has no changes of its own.
- `0f84a30ec69` Merge the updated settings-ui layer into chats again,
for #30612's read-only View fix; no changes of its own.
- `fb37822f985` fix(coderd/x/chatd/chattool): keep truncated skill index
descriptions within 1,024 runes. The cut now happens at 1,023 runes so
the ellipsis fits; the existing `skill_test.go` assertion now expects
1,023 runes plus the ellipsis.
- `1543666b584` docs(docs/ai-coder/agents): state the 1,023-character
cut before the skill index ellipsis.
- `96f1da47c9a` and `13f03d095ff` merge the updated settings-ui layer
for #30612's cache and Skills link fixes; no changes of their own.
- `b03c14c86de` and `41cc078b85a` merge the updated settings-ui layer;
`b03c14c86de` moves the `AgentChatPage.tsx` and `ChatMessageInput.tsx`
call sites, and their tests and stories, to #30612's split
`organizationSkills(...)` query.
- `1a32d05c9bc`
test(site/src/pages/AgentsPage/components/ChatMessageInput): restore
per-source loading stories for the slash menu.
- `830b0466982` fix(coderd/x/chatd): fail turn preparation when
organization skills cannot load. Main now returns database errors from
turn preparation (#30492); organization skills still logged and dropped
the failure, so a failed read silently hid them from the model. The new
`TestFetchOrganizationSkillMetadataListFailure` covers the returned
error.
- `84c135f8801` and `a6f8f63ad13` merge the updated settings-ui layer,
which brings in main; they resolve `generation_preparer.go` against
main's turn preparation error handling.
- `19b7880840f` merges #30612's member page test change; no changes of
its own.
- `c74d597f3c5` merges #30612's read-only status change; no changes of
its own.
- `f89c232c081` merges #30612's skills test changes; no changes of its
own.
- `17d5b9bfbc5` docs(docs/ai-coder/agents): describe the member skills
organization picker and read-only Enabled status.
- `f97b1710f71` merges the updated settings-ui layer (main at
`e7b76872098`); no changes of its own.

## Size

Production +558/-213 (docs +116/-6), tests +895/-262; total +1453/-475.
This is above the 500-line reviewer-friendly limit on purpose: Mike
asked for 4 to 5 PRs instead of the 21 small ones this stack replaces.

## Replaces

#30593 (skill sources), #30594 (chatd), #30601 (alias helper), #30602
(slash menu), #30604 (docs).

## Validation

- Go: all 21 packages under `coderd/x/skills` and `coderd/x/chatd` pass
on `62dbbd2dfd3`, plus the coverage comparisons above;
`coderd/x/chatd/chattool` passes again on `13f03d095ff` after the
truncation fix.
- Site: `pnpm run lint` and Biome clean; Vitest 102 tests; Storybook
Vitest 49 + 4 tests. `pnpm run lint` reran clean on `13f03d095ff`.
- On `a6f8f63ad13`, this PR's head before the test-only `19b7880840f`
merge: `go test` passes for `coderd/x/skills`,
`coderd/x/chatd/chattool`, and the `coderd/x/chatd` skill tests (`-run
'OrganizationSkill|Skill'`); 38 Vitest files covering skills and the
slash menu pass, 542 tests with 2 skipped.
- Docs: markdownlint 0 findings, Vale 0 findings.
- On `17d5b9bfbc5`: Vale clean, markdownlint and `make pre-commit` pass.
On `f97b1710f71`: `go build`, the `coderd/x/skills` and `chattool`
tests, `pnpm check` and `tsc` pass.
- Remote UAT round 7 through Coder Agents: PASS
([chat](https://dogfood.cdr.dev/agents/3426d4d3-2139-4ae1-8e0c-72ddeff413a8)).
- Full run on `62dbbd2dfd3`, including an in-place upgrade from main
`50c785cc6d7`: personal skills kept their IDs, names, content hashes and
timestamps, came up enabled, and worked in chats (`read_skill`) and the
`/` menu; create, edit, download and delete worked after the upgrade.
The admin page, sharing, the Enabled toggle, the member section, the `/`
menu, chats reading organization skills as the owner, limits, audit,
authorization and scoped keys, and the docs all passed.
- Delta run on `7349eac4389`: an update-only key gets 404 on PATCH with
no content in the response; saving permissions refreshes Updated without
a reload; smoke of the admin page, auditor View and Download, the `/`
menu and `read_skill`.
- Delta run on `0f84a30ec69` for `aaa356f0fd5`: read-only View, as an
org auditor and as a member, shows no Name hint, focuses no field and
starts on Close, and Escape or Close returns focus to the row menu
button; Add skill and Edit still show the hint and focus the import
field, and a saved edit persisted; smoke of the admin page, the `/` menu
organization group and `read_skill`. Screen-reader behavior was not
tested.
- Delta run on `13f03d095ff` for `698dd83946d`, `f82573cd1c2`,
`0e55137de7b` and `fb37822f985`: for an organization admin of org B who
is a plain member of org A, the sidebar Skills link drops `?org=` for
org A on seven AI settings pages and opens org B's skills, keeps `?org=`
for org B, and a typed `/ai/settings/skills?org=` for org A still shows
the permission error. A skill deleted and recreated with the same name
loads a fresh sharing list showing only Everyone, with no stale grant. A
1,500-character description appears in the chat's skill index as 1,023
characters plus an ellipsis, while `read_skill` returns all of it. Smoke
of the admin toggle, the member section, the `/` menu organization group
and `read_skill`.
- Low findings: the read-only View hint and field focus, fixed in
`aaa356f0fd5` and verified by the delta run above. The member section's
always-on disabled Enabled switch (also in the old stack) is replaced by
a read-only status icon in #30612's `63bb42754e3`, which has no UAT run.
Not fixed: `/` shows the `/personal/` prefix while organization skills
fail to load (the unknown-list rule above); the shared Switch
component's disabled styling (unchanged from main). A user who can read
skills in only one organization sees no organization name on the Skills
page, because the picker is hidden for a single organization, as on the
MCP servers page on main.
- Not tested: the workspace skills group (no running agent on the test
deployment), the 100-per-user personal cap, and behavior without a
Premium license.
- Remote UAT round 8 through Coder Agents: PASS on `b03c14c86de` (same
chat). The remote grader marked the unknown `read_skill` item FAIL only
because the prompt asked for the literal phrase "skill not found"; the
result names the skill once and says "not found" once, the same format
as main, so the runner graded it PASS on intent.
- Member page: starts on the default organization, shows one
organization's table with the read-only note once, Export all downloads
only the selected organization's skills, the picker is hidden with one
organization, and an organization without enabled skills isn't listed.
- Personal and admin tables: create, edit, toggle and delete each
refetch the list; reopening the editor shows the new content even with
the detail request delayed; a toggle changes state once, with no
flicker. A skill deleted and recreated with the same name shows only
Everyone in sharing.
- The sidebar Skills link keeps `?org=` only for an organization whose
skills the user can read. A create over 64 KiB returns 400 with the
detail "got 70000 bytes, maximum is 65536 bytes: skill is too large",
the cause once. The `/` menu shows Commands, Personal skills and
Organization skills, and invoking an organization skill loads its body
through `read_skill`.
- New low findings, not fixed: the member page picker's listbox is
labeled "Suggestions" (likely from the shared
`OrganizationAutocomplete`); a typed body over 64 KiB shows only the
size counter and a disabled Create until Import; `/ai/settings?org=`
redirects to the models page without `?org=`. The first and third were
not checked against main.
- `9002dc60382`, `1a32d05c9bc`, `830b0466982`, `ac3e62c83b7`,
`63bb42754e3`, `82b2487ad17`, `17d5b9bfbc5` and the main merges came
after `b03c14c86de`; they have tests but no UAT run.
- Every UAT round ran the migration as `000615_skills`. The heads ship
the same up and down SQL as `000621_skills`, so the upgrade path from
main's 000620 to 000621 has no UAT run.

> Xum opened this PR on behalf of @ibetitsmike.
2026-10-13 17:13:36 +00:00
…
…
…
…

Coder Logo Light Coder Logo Dark

Self-Hosted Cloud Development Environments and AI Agents

Coder Banner Light Coder Banner Dark

Quickstart | Docs | Why Coder | Premium

discord release godoc OpenSSF Best Practices OpenSSF Scorecard license Ask DeepWiki

Coder is a self-hosted platform for cloud development environments and AI coding agents. Workspaces are defined with Terraform, connected through a secure Wireguard® tunnel, and automatically shut down when not used. Coder Agents runs a native AI coding agent whose loop executes in the control plane on your infrastructure, with no API keys in workspaces.

  • Define cloud development environments in Terraform
    • EC2 VMs, Kubernetes Pods, Docker Containers, etc.
  • Automatically shutdown idle resources to save on costs
  • Onboard developers in seconds instead of days
  • Delegate coding work to AI agents on your infrastructure
    • Bring any model (Anthropic, OpenAI, Google, Bedrock, self-hosted)
    • No LLM credentials in workspaces, user identity on every action
    • Centralized model governance, cost tracking, and audit logging

Coder platform showing templates and a running workspace

Quickstart

Check out our install guides for other methods and a complete tutorial.

Try Coder with the install script on Linux and macOS, or grab the latest binary or installer from GitHub Releases on Windows:

curl -fsSL https://coder.com/install.sh | sh

Start the server and open http://localhost:3000 to create your initial user, create a Docker template, and provision your first workspace:

coder server

For a production deployment, add a PostgreSQL database (version 13 or later) and an external access URL, and see our validated architectures for sizing and infrastructure guidance:

coder server --postgres-url <url> --access-url <url>

Without these flags, Coder uses a built-in database and sets up a *.try.coder.app access URL for evaluation. Use coder --help for the full list of flags and environment variables.

Documentation

Browse the documentation or visit a specific section below:

  • Workspaces: Workspaces contain the IDEs, dependencies, and configuration information needed for software development
  • Templates: Templates are written in Terraform and describe the infrastructure for workspaces
  • Coder Agents: Delegate coding work to AI agents running on your self-hosted infrastructure
  • AI Gateway: Centralize authentication, auditing, and cost controls for AI tooling
  • Administration: Learn how to operate Coder
  • Premium: Learn about paid features built for large teams
  • IDEs: Connect your existing editor to a workspace

Support

Open an issue for bugs and feature requests.

For community support, showcasing what you built, and feedback on in-progress features, join our Discord or GitHub Discussions.

Dedicated support is included in Coder Premium. For more information, visit coder.com/pricing.

Integrations

New integrations are always in progress. Open an issue to request one. Contributions are welcome in any official or community repository.

Official

Community

Contributing

New contributors are always welcome. If you are new to the Coder codebase, see the contribution guide to get started.

Hiring

Apply on the careers page if you are interested in joining the team.

S
Description
Provision remote development environments via Terraform
Readme AGPL-3.0
1,022 MiB
Languages
Go 74.9%
TypeScript 23.1%
Shell 0.8%
HCL 0.3%
PLpgSQL 0.3%
Other 0.4%