SC-7 HTTP routes for the agent-config surface #629

Closed
opened 2026-05-01 10:34:44 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As a frontend integrator, I want every per-kind list / read / write / fork / delete / history route exposed under a consistent /agent-config/... surface, so that the dashboard can read and mutate any artifact at any scope without bespoke endpoints per kind.

Acceptance criteria

Routes

  • GET /agent-config — debug endpoint: every artifact resolved for the calling agent (or a given ?agent=name query). Returns a flat list with kind + name + scope + body + provenance.
  • Per kind (one route block each: skills, system-prompts, plugins, marketplaces, mcp):
    • GET /agent-config/{kind} — list all rows with optional ?effective_for=<agent> filter that returns the resolved layered view.
    • GET /agent-config/{kind}/{name}?scope=...&agent_type=...&instance_id=...
    • PUT /agent-config/{kind}/{name} body { scope, agent_type?, instance_id?, body, comment? } — upsert; writes a config_revision row before applying.
    • DELETE /agent-config/{kind}/{name}?scope=...&agent_type=...&instance_id=... — drops the row, writes a "deleted" revision (snapshot is the prior body for restore).
    • POST /agent-config/{kind}/{name}/fork body { from_scope, to_scope, agent_type?, instance_id? } — resolves the effective body for from_scope and writes it into the target scope.
    • GET /agent-config/{kind}/{name}/revisions — paginated history.
    • POST /agent-config/{kind}/{name}/revisions/{id}/restore — writes a new revision whose body is the snapshot of the targeted revision.

Transactionality + auth

  • Every mutation runs inside a transaction: write the config_revision row first, then apply the change. A rollback leaves no orphan revision.
  • All mutating routes go through the existing guardMutating rail.
  • Read routes (GET) are operator-auth-gated under the same SPA session pattern as /agents today.
  • Response envelopes match the existing apps/server/src/main.ts style ({ ok: true, data: ... } / { ok: false, error: ... }).

After-effects

  • Successful mutations enqueue a re-render via agent-env-sync.renderForInstance (SC-2) for every affected instance.
  • SSE event agent_config_changed { kind, name, scope, agent_type, instance_id } so the dashboard's TanStack Query caches can invalidate without polling.

Tests

  • Unit: every route's happy + 404 + 400 paths.
  • Unit: revision write happens before the row update — failed validation leaves no orphan revision (transaction rollback covers).
  • Integration: an end-to-end fork flow (operator forks a builtin skill into agent_type, edits, restores a prior revision) leaves the DB in a consistent state.

Out of scope

  • WebSocket push of config changes (poll-based refresh + targeted SSE event is enough for v1).
  • Bulk import / export.

References

  • specs/agent-config-customization.md §API surface and §Story SC-7
  • Depends on SC-1 (tables) and SC-2 (renderer) so writes propagate.
## User story As a frontend integrator, I want every per-kind list / read / write / fork / delete / history route exposed under a consistent `/agent-config/...` surface, so that the dashboard can read and mutate any artifact at any scope without bespoke endpoints per kind. ## Acceptance criteria ### Routes - [ ] `GET /agent-config` — debug endpoint: every artifact resolved for the calling agent (or a given `?agent=name` query). Returns a flat list with kind + name + scope + body + provenance. - [ ] Per kind (one route block each: skills, system-prompts, plugins, marketplaces, mcp): - [ ] `GET /agent-config/{kind}` — list all rows with optional `?effective_for=<agent>` filter that returns the resolved layered view. - [ ] `GET /agent-config/{kind}/{name}?scope=...&agent_type=...&instance_id=...` - [ ] `PUT /agent-config/{kind}/{name}` body `{ scope, agent_type?, instance_id?, body, comment? }` — upsert; writes a `config_revision` row before applying. - [ ] `DELETE /agent-config/{kind}/{name}?scope=...&agent_type=...&instance_id=...` — drops the row, writes a "deleted" revision (snapshot is the prior body for restore). - [ ] `POST /agent-config/{kind}/{name}/fork` body `{ from_scope, to_scope, agent_type?, instance_id? }` — resolves the effective body for `from_scope` and writes it into the target scope. - [ ] `GET /agent-config/{kind}/{name}/revisions` — paginated history. - [ ] `POST /agent-config/{kind}/{name}/revisions/{id}/restore` — writes a new revision whose body is the snapshot of the targeted revision. ### Transactionality + auth - [ ] Every mutation runs inside a transaction: write the `config_revision` row first, then apply the change. A rollback leaves no orphan revision. - [ ] All mutating routes go through the existing `guardMutating` rail. - [ ] Read routes (GET) are operator-auth-gated under the same SPA session pattern as `/agents` today. - [ ] Response envelopes match the existing `apps/server/src/main.ts` style (`{ ok: true, data: ... }` / `{ ok: false, error: ... }`). ### After-effects - [ ] Successful mutations enqueue a re-render via `agent-env-sync.renderForInstance` (SC-2) for every affected instance. - [ ] SSE event `agent_config_changed` `{ kind, name, scope, agent_type, instance_id }` so the dashboard's TanStack Query caches can invalidate without polling. ### Tests - [ ] Unit: every route's happy + 404 + 400 paths. - [ ] Unit: revision write happens **before** the row update — failed validation leaves no orphan revision (transaction rollback covers). - [ ] Integration: an end-to-end fork flow (operator forks a builtin skill into agent_type, edits, restores a prior revision) leaves the DB in a consistent state. ## Out of scope - WebSocket push of config changes (poll-based refresh + targeted SSE event is enough for v1). - Bulk import / export. ## References - `specs/agent-config-customization.md` §API surface and §Story SC-7 - Depends on **SC-1** (tables) and **SC-2** (renderer) so writes propagate.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#629
No description provided.