fix(api-catalog): say Agent Chat is always on instead of offering a retired toggle (#20169)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents learn what the API can do from the API catalog at
`/api/openapi.json`
> - PR #19360 made Agent Chat standard. The `enableAgentChat` key is now
retired: it always reads true, and the app ignores written values
> - The catalog still lists `enableAgentChat` as an ordinary boolean on
the experimental settings operations, with no note that it is retired
> - An agent that was asked to "Enable Agent Chat on this instance" read
the catalog and told the person to turn on a toggle in Instance Settings
→ Experimental. That toggle no longer exists
> - This pull request adds a note to both experimental settings
operations: Agent Chat is always on, the key is retired, and agents must
tell people it is already on
> - The benefit is that agents give a correct answer and do not send
people to a control that is not there

## Linked Issues or Issue Description

Bug report (no public issue exists).

**What happened**
An agent was asked "Enable Agent Chat on this instance." It read `PATCH
/api/instance/settings/experimental` in the API catalog and found
`enableAgentChat`. It replied that an admin must open Instance Settings
→ Experimental and turn on Enable Agent Chat. That toggle was removed in
#19360, and Agent Chat is already on for everyone.

**Expected behavior**
The agent says that Agent Chat is already on (the person is using it),
and that nothing must be enabled.

**Steps to reproduce**
1. Open a chat with an agent on any current instance.
2. Send "Enable Agent Chat on this instance."
3. The agent reads the experimental settings operation in the API
catalog and sends you to a settings toggle that does not exist.

Refs #19360

## What Changed

- `server/src/routes/openapi.ts`: the GET and PATCH
`/api/instance/settings/experimental` operations now say that Agent Chat
is always on, that `enableAgentChat` is a retired compatibility key that
always reads true and ignores written values, and that agents must tell
people it is already on instead of sending them to a toggle.
- `server/src/__tests__/openapi-routes.test.ts`: a regression test
checks this note on both operations.
- The note says Agent Chat "needs no setup" instead of "there is nothing
to enable", so it does not match unrelated keyword searches. The runner
API no-results test (`nothing-zzzzzzzzzz`) had matched the word
"nothing".

## Verification

- `cd server && npx vitest run src/__tests__/openapi-routes.test.ts
src/services/native-runtime/runner-api.test.ts` passes (2108 tests), and
the server `tsc --noEmit` passes.
- The chat eval `instance-operations.instance-settings` found this
defect. Its run log shows that the agent reasoned from the catalog
schema ("The setting is `enableAgentChat` on PATCH
/api/instance/settings/experimental").

## Risks

- Low risk. This changes only catalog description text. It does not
change behavior, validation or the schema.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution, used through Claude Code.

## 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
- [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 updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DottaandClaude Opus 5.5 authored and GitHub committed 2026-11-09 00:11:13 -06:00
1 parent b07399c241
commit 7086019d4b
2 files changed
+12 -1

No files matched your search

@@ -576,6 +576,16 @@ describe("openapi routes", () => {
expect(dismiss.description).toContain("viewers may dismiss their own"); expect(dismiss.description).toContain("viewers may dismiss their own");
}); });
it("tells agents that Agent Chat is always on instead of advertising a retired toggle", async () => {
const res = await request(createApp()).get("/api/openapi.json");
const experimental = res.body.paths["/api/instance/settings/experimental"];
for (const operation of [experimental.get, experimental.patch]) {
expect(operation.description).toContain("Agent Chat is always on");
expect(operation.description).toContain("enableAgentChat is a retired compatibility key");
expect(operation.description).toContain("tell them it is already on");
}
});
it("tells agents that archiving keeps a status card and where a person restores it", async () => { it("tells agents that archiving keeps a status card and where a person restores it", async () => {
const res = await request(createApp()).get("/api/openapi.json"); const res = await request(createApp()).get("/api/openapi.json");
const patch = res.body.paths["/api/status-cards/{id}"].patch; const patch = res.body.paths["/api/status-cards/{id}"].patch;
+2 -1
View File
@@ -7120,6 +7120,7 @@ registry.registerPath({
path: "/api/instance/settings/experimental", path: "/api/instance/settings/experimental",
tags: ["instance"], tags: ["instance"],
summary: "Get experimental instance settings", summary: "Get experimental instance settings",
description: "Agent Chat is always on for every person on every instance and needs no setup. enableAgentChat is a retired compatibility key: it always reads true and written values are ignored. If someone asks to enable Agent Chat, tell them it is already on, since they are using it now; do not send them to a settings toggle.",
responses: { 200: r.ok(), 401: r.unauthorized }, responses: { 200: r.ok(), 401: r.unauthorized },
}); });
@@ -7128,7 +7129,7 @@ registry.registerPath({
path: "/api/instance/settings/experimental", path: "/api/instance/settings/experimental",
tags: ["instance"], tags: ["instance"],
summary: "Update experimental instance settings", summary: "Update experimental instance settings",
description: "Requires instance-admin access or a trusted Cloud stack admin. Operator-hidden settings and Cloud-managed feature restrictions still apply. This does not grant access to other instance administration operations.", description: "Requires instance-admin access or a trusted Cloud stack admin. Operator-hidden settings and Cloud-managed feature restrictions still apply. This does not grant access to other instance administration operations. Agent Chat is always on for every person on every instance and needs no setup. enableAgentChat is a retired compatibility key: it always reads true and written values are ignored. If someone asks to enable Agent Chat, tell them it is already on, since they are using it now; do not send them to a settings toggle.",
request: { body: jsonBody(patchInstanceExperimentalSettingsSchema) }, request: { body: jsonBody(patchInstanceExperimentalSettingsSchema) },
responses: { 200: r.ok(), 400: r.badRequest, 401: r.unauthorized, 403: r.forbidden }, responses: { 200: r.ok(), 400: r.badRequest, 401: r.unauthorized, 403: r.forbidden },
}); });