Files
PaperClipAI/server
Devin Foley 176a9e8230 fix(built-in-agents): allow first-time setup of a needs_setup built-in under board-approval policy (#10129)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Companies can require **board approval for new agents**; built-in
agents (e.g. the Reflection Coach / Briefs) are provisioned through the
`built-in-agents` service `provision()`
> - Some built-in agents are *auto-provisioned* as a hire that, once
approved, resolves to an idle agent row whose `adapterConfig` is still
empty — status `needs_setup`
> - When the board operator then opens that agent's setup dialog and
submits the adapter config, `provision()` saw
`adapterType`/`adapterConfig` on an already-existing row and classified
it as a **reconfiguration**, throwing a dead-end 409: *"Built-in agent
adapter changes require board approval before they can be applied."*
> - The operator *is* the board, so there was no one left to grant an
approval they already implicitly hold — setup could never be completed
> - This pull request treats first-time adapter setup of a `needs_setup`
built-in as the first-time configuration it actually is, applying it
directly while still gating genuine reconfiguration of a live agent
> - The benefit is the board can finish setting up an auto-provisioned
built-in agent without hitting an unsatisfiable approval wall

## Linked Issues or Issue Description

<!-- No public GitHub issue exists; describing the underlying bug in-PR
following the bug_report template. -->

**What happened?**

With "require board approval for new agents" enabled, completing the
adapter setup of an auto-provisioned but unconfigured built-in agent
(status `needs_setup`, e.g. the Reflection Coach) failed with a 409 —
*"Built-in agent adapter changes require board approval before they can
be applied."* — even for the board user. Because the operator *is* the
board, no additional approver existed, so setup was permanently blocked.
Root cause: in `builtInAgentService.provision()`, any request carrying
`adapterType`/`adapterConfig` against an existing row was treated as a
reconfiguration and gated, regardless of whether that row had ever
completed its initial adapter setup. An auto-provisioned hire resolves
to an idle row with an empty `adapterConfig` (`needs_setup`), so its
very first configuration was misclassified.

**Expected behavior**

The board can complete first-time setup of an already-sanctioned
built-in agent without a fresh approval, matching the behavior when
board approval is not required. Genuine reconfiguration of an
already-configured (`ready`/`paused`) agent should still require
approval.

**Steps to reproduce**

1. In a company with `requireBoardApprovalForNewAgents` enabled, have a
built-in agent auto-provisioned so its row exists but its adapter is
unconfigured (status `needs_setup`).
2. As the board user, open that agent's setup dialog and submit an
adapter type + config.
3. Observe the 409 "Built-in agent adapter changes require board
approval before they can be applied." with no way for the board to grant
the approval.

**Deployment mode**

Local single-instance / self-hosted (server `built-in-agents` service).

## What Changed

- `server/src/services/built-in-agents.ts`: In `provision()`, when the
existing built-in row has **not** yet completed adapter setup
(`!hasCompleteAdapterConfig(...)`, i.e. `needs_setup`), first-time
adapter configuration now applies directly via `ensure()` — the same
path used when board approval is not required. The hire that created the
row was already sanctioned, so no fresh approval is required.
- Reconfiguration of an already-configured (`ready`/`paused`) built-in
agent stays gated behind board approval exactly as before, and
`pending_approval` rows are handled before the new branch.
- `server/src/__tests__/built-in-agents.test.ts`: Added a regression
test — under `requireApproval: true`, completing first-time setup of a
`needs_setup` built-in returns `approval: null`, transitions the agent
to `ready`, and creates **no** approval row.

## Verification

```bash
cd server
npx vitest run src/__tests__/built-in-agents.test.ts
# Test Files  1 passed (1)
#       Tests  31 passed (31)
```

- New test `completes first-time setup of a needs_setup built-in without
a fresh board approval` passes.
- Full `built-in-agents.test.ts` suite (31 tests) passes, including
existing tests that assert genuine reconfiguration of a configured agent
**remains** gated.

## Risks

Low risk. The change narrows an over-broad approval gate: it only opens
the direct-apply path for rows that have never completed adapter setup
(`needs_setup`), determined by the existing `hasCompleteAdapterConfig`
predicate that already drives `deriveBuiltInAgentStatus`.
Already-configured (`ready`/`paused`) agents, and `pending_approval`
rows, are unaffected and still gated. No schema or migration changes.

## Model Used

Claude Opus 4.8 (`claude-opus-4-8`), 1M context, extended thinking, with
tool use / code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above (searched my open PRs and compared patch-ids — no duplicate
exists)
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-07-23 14:53:15 -07:00
..