<a id="api-management"></a>
# Agent·LLM·Tool·관리 API 전수 참조

agent, LLM, tool, MCP, skill, company, intercept와 sync 영역의 등록 operation을 전수 색인한다. 이 페이지는 route/address/auth/handler 요약이고 field-level 계약은 [API 의미 schema](schema-reference.md#api-schema-reference)가 소유한다.

> **분모** · 이 페이지 82개 / 전체 261개. route 등록·auth·직접 handler는 C다. 요청/응답 semantic은 operation별 C/P/U를 분리하며 route 수를 semantic 완료율로 쓰지 않는다.

## Operation 색인

| operation | handler | auth | 입력 | status | schema |
|---|---|---|---|---|---|
| [`GET /api/llm`](#op-get-api-llm) | `getLLM` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401` | [P](schema-reference.md#schema-get-api-llm) |
| [`POST /api/llm`](#op-post-api-llm) | `setLLM` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500` | [P](schema-reference.md#schema-post-api-llm) |
| [`POST /api/llm/test`](#op-post-api-llm-test) | `testLLM` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401` | [P](schema-reference.md#schema-post-api-llm-test) |
| [`GET /api/llm/records`](#op-get-api-llm-records) | `pgListLLMRecords` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query model,page,session,size,task | `200/401/500` | [P](schema-reference.md#schema-get-api-llm-records) |
| [`DELETE /api/llm/records`](#op-delete-api-llm-records) | `pgDeleteLLMRecords` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/400/401/500` | [P](schema-reference.md#schema-delete-api-llm-records) |
| [`GET /api/llm/records/tasks`](#op-get-api-llm-records-tasks) | `pgLLMTasks` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500` | [P](schema-reference.md#schema-get-api-llm-records-tasks) |
| [`GET /api/llm/records/by-model`](#op-get-api-llm-records-by-model) | `pgTokenByModel` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/400/401/500` | [P](schema-reference.md#schema-get-api-llm-records-by-model) |
| [`GET /api/llm/records/{id}`](#op-get-api-llm-records-id) | `pgGetLLMRecord` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404` | [P](schema-reference.md#schema-get-api-llm-records-id) |
| [`GET /api/chat/mentions`](#op-get-api-chat-mentions) | `searchChatMentions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query cursor,kind,q | `200/400/401/500/503` | [P](schema-reference.md#schema-get-api-chat-mentions) |
| [`POST /api/chat`](#op-post-api-chat) | `chat` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task; JSON | `200/202/400/401/404/409/500` | [P](schema-reference.md#schema-post-api-chat) |
| [`POST /api/chat/upload`](#op-post-api-chat-upload) | `chatUpload` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query id,scope; multipart/form-data | `200/400/401/404/409/500` | [P](schema-reference.md#schema-post-api-chat-upload) |
| [`GET /api/conversations`](#op-get-api-conversations) | `pgListConversations` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-conversations) |
| [`POST /api/conversations`](#op-post-api-conversations) | `pgCreateConversation` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/404/413/500/503` | [P](schema-reference.md#schema-post-api-conversations) |
| [`POST /api/conversations/delete/batch`](#op-post-api-conversations-delete-batch) | `pgDeleteConversationsBatch` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/413/500/503` | [P](schema-reference.md#schema-post-api-conversations-delete-batch) |
| [`PATCH /api/conversations/{id}`](#op-patch-api-conversations-id) | `pgRenameConversation` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/413/500/503` | [P](schema-reference.md#schema-patch-api-conversations-id) |
| [`PATCH /api/conversations/{id}/profile`](#op-patch-api-conversations-id-profile) | `pgUpdateConversation` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/413/500/503` | [C](schema-reference.md#schema-patch-api-conversations-id-profile) |
| [`DELETE /api/conversations/{id}`](#op-delete-api-conversations-id) | `pgDeleteConversation` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500/503` | [P](schema-reference.md#schema-delete-api-conversations-id) |
| [`GET /api/conversations/{id}/messages`](#op-get-api-conversations-id-messages) | `pgConversationMessages` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query before,limit,since | `200/400/401/404/500/503` | [P](schema-reference.md#schema-get-api-conversations-id-messages) |
| [`POST /api/conversations/{id}/messages`](#op-post-api-conversations-id-messages) | `pgSendConversationMessage` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `202/400/401/404/409/500/503` | [C](schema-reference.md#schema-post-api-conversations-id-messages) |
| [`POST /api/conversations/{id}/stop`](#op-post-api-conversations-id-stop) | `pgStopConversation` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500/503` | [C](schema-reference.md#schema-post-api-conversations-id-stop) |
| [`GET /api/conversations/{id}/messages/{seq}`](#op-get-api-conversations-id-messages-seq) | `pgConversationMsgDetail` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id,seq | `200/400/401/404/500/503` | [P](schema-reference.md#schema-get-api-conversations-id-messages-seq) |
| [`GET /api/agents`](#op-get-api-agents) | `pgListAgents` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-agents) |
| [`POST /api/agents`](#op-post-api-agents) | `pgCreateAgent` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/409/500/503` | [P](schema-reference.md#schema-post-api-agents) |
| [`GET /api/agents/{key}`](#op-get-api-agents-key) | `pgGetAgent` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-get-api-agents-key) |
| [`PATCH /api/agents/{key}`](#op-patch-api-agents-key) | `pgUpdateAgent` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [C](schema-reference.md#schema-patch-api-agents-key) |
| [`DELETE /api/agents/{key}`](#op-delete-api-agents-key) | `pgDeleteAgent` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/400/401/404/500/503` | [P](schema-reference.md#schema-delete-api-agents-key) |
| [`PUT /api/agents/{key}/config`](#op-put-api-agents-key-config) | `pgSaveAgentConfig` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [P](schema-reference.md#schema-put-api-agents-key-config) |
| [`PUT /api/agents/{key}/prompt`](#op-put-api-agents-key-prompt) | `pgSavePrompt` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [P](schema-reference.md#schema-put-api-agents-key-prompt) |
| [`POST /api/agents/{key}/prompt/reset`](#op-post-api-agents-key-prompt-reset) | `pgResetPrompt` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/400/401/404/500/503` | [P](schema-reference.md#schema-post-api-agents-key-prompt-reset) |
| [`PUT /api/agents/{key}/wrapup`](#op-put-api-agents-key-wrapup) | `pgSaveWrapup` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [C](schema-reference.md#schema-put-api-agents-key-wrapup) |
| [`POST /api/agents/{key}/wrapup/reset`](#op-post-api-agents-key-wrapup-reset) | `pgResetWrapup` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-post-api-agents-key-wrapup-reset) |
| [`PUT /api/agents/{key}/wrapup/task-timeout`](#op-put-api-agents-key-wrapup-task-timeout) | `pgSaveTaskTimeoutWrapup` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [C](schema-reference.md#schema-put-api-agents-key-wrapup-task-timeout) |
| [`POST /api/agents/{key}/wrapup/task-timeout/reset`](#op-post-api-agents-key-wrapup-task-timeout-reset) | `pgResetTaskTimeoutWrapup` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-post-api-agents-key-wrapup-task-timeout-reset) |
| [`GET /api/agents/{key}/triggers`](#op-get-api-agents-key-triggers) | `pgListTriggers` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-get-api-agents-key-triggers) |
| [`POST /api/agents/{key}/triggers`](#op-post-api-agents-key-triggers) | `pgCreateTrigger` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [P](schema-reference.md#schema-post-api-agents-key-triggers) |
| [`GET /api/agents/{key}/prompts`](#op-get-api-agents-key-prompts) | `pgListPromptVersions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-get-api-agents-key-prompts) |
| [`GET /api/agents/{key}/variables`](#op-get-api-agents-key-variables) | `pgPromptVars` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-get-api-agents-key-variables) |
| [`POST /api/agents/{key}/prompt/preview`](#op-post-api-agents-key-prompt-preview) | `pgPreviewPrompt` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/401/404/500/503` | [P](schema-reference.md#schema-post-api-agents-key-prompt-preview) |
| [`GET /api/agents/{key}/visibility`](#op-get-api-agents-key-visibility) | `pgGetAgentVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [P](schema-reference.md#schema-get-api-agents-key-visibility) |
| [`PUT /api/agents/{key}/visibility`](#op-put-api-agents-key-visibility) | `pgSetAgentVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [C](schema-reference.md#schema-put-api-agents-key-visibility) |
| [`GET /api/tools`](#op-get-api-tools) | `pgListTools` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-tools) |
| [`PUT /api/tools/{key}`](#op-put-api-tools-key) | `pgUpdateTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/404/500/503` | [C](schema-reference.md#schema-put-api-tools-key) |
| [`POST /api/tools/custom`](#op-post-api-tools-custom) | `pgCreateCustomTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/409/500/503` | [P](schema-reference.md#schema-post-api-tools-custom) |
| [`POST /api/tools/custom/test`](#op-post-api-tools-custom-test) | `pgTestCustomTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/503` | [P](schema-reference.md#schema-post-api-tools-custom-test) |
| [`PUT /api/tools/custom/{key}`](#op-put-api-tools-custom-key) | `pgUpdateCustomTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key; JSON | `200/400/401/500/503` | [C](schema-reference.md#schema-put-api-tools-custom-key) |
| [`DELETE /api/tools/custom/{key}`](#op-delete-api-tools-custom-key) | `pgDeleteCustomTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/500/503` | [P](schema-reference.md#schema-delete-api-tools-custom-key) |
| [`POST /api/tools/{key}/reset`](#op-post-api-tools-key-reset) | `pgResetTool` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path key | `200/401/404/500/503` | [C](schema-reference.md#schema-post-api-tools-key-reset) |
| [`GET /api/mcp`](#op-get-api-mcp) | `pgListMCP` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-mcp) |
| [`POST /api/mcp`](#op-post-api-mcp) | `pgSaveMCP` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [P](schema-reference.md#schema-post-api-mcp) |
| [`DELETE /api/mcp/{id}`](#op-delete-api-mcp-id) | `pgDeleteMCP` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/401/500/503` | [P](schema-reference.md#schema-delete-api-mcp-id) |
| [`GET /api/mcp/{id}/tools`](#op-get-api-mcp-id-tools) | `pgMCPTools` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/401/500/503` | [P](schema-reference.md#schema-get-api-mcp-id-tools) |
| [`POST /api/mcp/{id}/refresh`](#op-post-api-mcp-id-refresh) | `pgRefreshMCP` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/401/404/500/502/503` | [P](schema-reference.md#schema-post-api-mcp-id-refresh) |
| [`GET /api/skills`](#op-get-api-skills) | `fsListSkills` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500` | [P](schema-reference.md#schema-get-api-skills) |
| [`POST /api/skills`](#op-post-api-skills) | `fsCreateSkill` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `201/400/401/409/500` | [P](schema-reference.md#schema-post-api-skills) |
| [`POST /api/skills/upload`](#op-post-api-skills-upload) | `fsUploadSkill` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query overwrite; multipart/form-data | `201/400/401/409/500` | [P](schema-reference.md#schema-post-api-skills-upload) |
| [`DELETE /api/skills/{name}`](#op-delete-api-skills-name) | `fsDeleteSkill` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name | `200/400/401/500/503` | [P](schema-reference.md#schema-delete-api-skills-name) |
| [`GET /api/skills/missing`](#op-get-api-skills-missing) | `fsMissingSkills` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query limit | `200/401/500/503` | [P](schema-reference.md#schema-get-api-skills-missing) |
| [`GET /api/skills/{name}/usage`](#op-get-api-skills-name-usage) | `fsSkillUsage` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name; query limit | `200/400/401/500/503` | [P](schema-reference.md#schema-get-api-skills-name-usage) |
| [`PUT /api/skills/{name}/meta`](#op-put-api-skills-name-meta) | `fsUpdateSkillMeta` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name; JSON | `200/400/401/404/500` | [C](schema-reference.md#schema-put-api-skills-name-meta) |
| [`POST /api/skills/{name}/dirs`](#op-post-api-skills-name-dirs) | `fsCreateDir` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name; JSON | `201/400/401/404/500` | [P](schema-reference.md#schema-post-api-skills-name-dirs) |
| [`GET /api/skills/{name}/files`](#op-get-api-skills-name-files) | `fsListFiles` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name | `200/400/401/404/500` | [P](schema-reference.md#schema-get-api-skills-name-files) |
| [`GET /api/skills/{name}/files/{file...}`](#op-get-api-skills-name-files-file) | `fsReadFile` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name,file | `200/400/401/404/500` | [P](schema-reference.md#schema-get-api-skills-name-files-file) |
| [`PUT /api/skills/{name}/files/{file...}`](#op-put-api-skills-name-files-file) | `fsWriteFile` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name,file; JSON | `200/400/401/404/500` | [C](schema-reference.md#schema-put-api-skills-name-files-file) |
| [`DELETE /api/skills/{name}/files/{file...}`](#op-delete-api-skills-name-files-file) | `fsDeletePath` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name,file | `200/400/401/404/500` | [P](schema-reference.md#schema-delete-api-skills-name-files-file) |
| [`GET /api/visibility/{kind}/{id}`](#op-get-api-visibility-kind-id) | `pgResourceVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path kind,id | `200/401/500/503` | [P](schema-reference.md#schema-get-api-visibility-kind-id) |
| [`POST /api/visibility/toggle`](#op-post-api-visibility-toggle) | `pgToggleVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [C](schema-reference.md#schema-post-api-visibility-toggle) |
| [`GET /api/visibility/skill/{name}`](#op-get-api-visibility-skill-name) | `pgSkillVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path name | `200/401/500/503` | [P](schema-reference.md#schema-get-api-visibility-skill-name) |
| [`POST /api/visibility/skill/toggle`](#op-post-api-visibility-skill-toggle) | `pgToggleSkillVisibility` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [C](schema-reference.md#schema-post-api-visibility-skill-toggle) |
| [`GET /api/llm/profiles`](#op-get-api-llm-profiles) | `pgListProfiles` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-llm-profiles) |
| [`POST /api/llm/profiles`](#op-post-api-llm-profiles) | `pgSaveProfile` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [P](schema-reference.md#schema-post-api-llm-profiles) |
| [`DELETE /api/llm/profiles/{id}`](#op-delete-api-llm-profiles-id) | `pgDeleteProfile` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/401/404/409/500/503` | [P](schema-reference.md#schema-delete-api-llm-profiles-id) |
| [`POST /api/llm/profiles/active`](#op-post-api-llm-profiles-active) | `pgActivateProfile` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [C](schema-reference.md#schema-post-api-llm-profiles-active) |
| [`GET /api/llm/retry-policy`](#op-get-api-llm-retry-policy) | `pgGetLLMRetryPolicy` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/503` | [P](schema-reference.md#schema-get-api-llm-retry-policy) |
| [`POST /api/llm/retry-policy`](#op-post-api-llm-retry-policy) | `pgSaveLLMRetryPolicy` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [P](schema-reference.md#schema-post-api-llm-retry-policy) |
| [`GET /api/llm/pool`](#op-get-api-llm-pool) | `pgLLMPoolStatus` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/503` | [P](schema-reference.md#schema-get-api-llm-pool) |
| [`POST /api/llm/pool/reset`](#op-post-api-llm-pool-reset) | `pgLLMPoolReset` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/503` | [P](schema-reference.md#schema-post-api-llm-pool-reset) |
| [`POST /api/llm/models`](#op-post-api-llm-models) | `pgListModels` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401` | [P](schema-reference.md#schema-post-api-llm-models) |
| [`GET /api/conversations/{id}/side-questions`](#op-get-api-conversations-id-side-questions) | `handleSideQuestions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query before | `200/400/401/404/500/503` | [P](schema-reference.md#schema-get-api-conversations-id-side-questions) |
| [`POST /api/conversations/{id}/side-questions`](#op-post-api-conversations-id-side-questions) | `handleSideQuestions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/202/400/401/404/409/429/500/503` | [P](schema-reference.md#schema-post-api-conversations-id-side-questions) |
| [`DELETE /api/conversations/{id}/side-questions`](#op-delete-api-conversations-id-side-questions) | `handleSideQuestions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500/503` | [C](schema-reference.md#schema-delete-api-conversations-id-side-questions) |
| [`GET /api/side-questions/{requestID}/events`](#op-get-api-side-questions-requestid-events) | `sideEvents` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path requestID | `200/401/404/500` | [P](schema-reference.md#schema-get-api-side-questions-requestid-events) |
| [`POST /api/side-questions/{requestID}/cancel`](#op-post-api-side-questions-requestid-cancel) | `cancelSideRequest` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path requestID | `200/401/404/500` | [C](schema-reference.md#schema-post-api-side-questions-requestid-cancel) |

<a id="op-get-api-llm"></a>
## `GET /api/llm`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getLLM` · `server/server.go` · [handler 근거](evidence:handler-get-api-llm) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-llm"></a>
## `POST /api/llm`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `setLLM` · `server/server.go` · [handler 근거](evidence:handler-post-api-llm) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-llm-test"></a>
## `POST /api/llm/test`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `testLLM` · `server/server.go` · [handler 근거](evidence:handler-post-api-llm-test) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm-test) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-llm-records"></a>
## `GET /api/llm/records`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListLLMRecords` · `server/commands.go` · [handler 근거](evidence:handler-get-api-llm-records) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `model, page, session, size, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-records) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-delete-api-llm-records"></a>
## `DELETE /api/llm/records`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteLLMRecords` · `server/commands.go` · [handler 근거](evidence:handler-delete-api-llm-records) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-llm-records) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-llm-records-tasks"></a>
## `GET /api/llm/records/tasks`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgLLMTasks` · `server/commands.go` · [handler 근거](evidence:handler-get-api-llm-records-tasks) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-records-tasks) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-llm-records-by-model"></a>
## `GET /api/llm/records/by-model`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgTokenByModel` · `server/commands.go` · [handler 근거](evidence:handler-get-api-llm-records-by-model) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-records-by-model) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-llm-records-id"></a>
## `GET /api/llm/records/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgGetLLMRecord` · `server/commands.go` · [handler 근거](evidence:handler-get-api-llm-records-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-records-id) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-chat-mentions"></a>
## `GET /api/chat/mentions`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `searchChatMentions` · `server/chat_mentions.go` · [handler 근거](evidence:handler-get-api-chat-mentions) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `cursor, kind, q` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-chat-mentions) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-chat"></a>
## `POST /api/chat`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `chat` · `server/server.go` · [handler 근거](evidence:handler-post-api-chat) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `JSON` |
| status/error | 직접 관찰 `200, 202, 400, 401, 404, 409, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-chat) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · agent turn을 background context에서 실행할 수 있음; activity/stop/terminal event를 확인 |

<a id="op-post-api-chat-upload"></a>
## `POST /api/chat/upload`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `chatUpload` · `server/chatupload.go` · [handler 근거](evidence:handler-post-api-chat-upload) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `id, scope` · body `multipart/form-data` |
| status/error | 직접 관찰 `200, 400, 401, 404, 409, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-chat-upload) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-conversations"></a>
## `GET /api/conversations`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListConversations` · `server/conversations.go` · [handler 근거](evidence:handler-get-api-conversations) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-conversations) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-conversations"></a>
## `POST /api/conversations`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgCreateConversation` · `server/conversations.go` · [handler 근거](evidence:handler-post-api-conversations) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-conversations) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-conversations-delete-batch"></a>
## `POST /api/conversations/delete/batch`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteConversationsBatch` · `server/conversations.go` · [handler 근거](evidence:handler-post-api-conversations-delete-batch) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-conversations-delete-batch) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-patch-api-conversations-id"></a>
## `PATCH /api/conversations/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgRenameConversation` · `server/conversations.go` · [handler 근거](evidence:handler-patch-api-conversations-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-patch-api-conversations-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-patch-api-conversations-id-profile"></a>
## `PATCH /api/conversations/{id}/profile`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgUpdateConversation` · `server/conversations.go` · [handler 근거](evidence:handler-patch-api-conversations-id-profile) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-patch-api-conversations-id-profile) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-conversations-id"></a>
## `DELETE /api/conversations/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteConversation` · `server/conversations.go` · [handler 근거](evidence:handler-delete-api-conversations-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-conversations-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-conversations-id-messages"></a>
## `GET /api/conversations/{id}/messages`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgConversationMessages` · `server/conversations.go` · [handler 근거](evidence:handler-get-api-conversations-id-messages) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `before, limit, since` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-conversations-id-messages) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · agent turn을 background context에서 실행할 수 있음; activity/stop/terminal event를 확인 |

<a id="op-post-api-conversations-id-messages"></a>
## `POST /api/conversations/{id}/messages`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSendConversationMessage` · `server/conversations.go` · [handler 근거](evidence:handler-post-api-conversations-id-messages) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `202, 400, 401, 404, 409, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-conversations-id-messages) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · agent turn을 background context에서 실행할 수 있음; activity/stop/terminal event를 확인 |

<a id="op-post-api-conversations-id-stop"></a>
## `POST /api/conversations/{id}/stop`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgStopConversation` · `server/conversations.go` · [handler 근거](evidence:handler-post-api-conversations-id-stop) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-conversations-id-stop) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-conversations-id-messages-seq"></a>
## `GET /api/conversations/{id}/messages/{seq}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgConversationMsgDetail` · `server/conversations.go` · [handler 근거](evidence:handler-get-api-conversations-id-messages-seq) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id, seq` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-conversations-id-messages-seq) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-agents"></a>
## `GET /api/agents`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListAgents` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-agents) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-agents"></a>
## `POST /api/agents`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgCreateAgent` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-agents) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 409, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-agents-key"></a>
## `GET /api/agents/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgGetAgent` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-agents-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents-key) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-patch-api-agents-key"></a>
## `PATCH /api/agents/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgUpdateAgent` · `server/server_mgmt.go` · [handler 근거](evidence:handler-patch-api-agents-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-patch-api-agents-key) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-agents-key"></a>
## `DELETE /api/agents/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteAgent` · `server/server_mgmt.go` · [handler 근거](evidence:handler-delete-api-agents-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-agents-key) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-agents-key-config"></a>
## `PUT /api/agents/{key}/config`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveAgentConfig` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-agents-key-config) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-put-api-agents-key-config) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-agents-key-prompt"></a>
## `PUT /api/agents/{key}/prompt`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSavePrompt` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-agents-key-prompt) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-put-api-agents-key-prompt) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-agents-key-prompt-reset"></a>
## `POST /api/agents/{key}/prompt/reset`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgResetPrompt` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-agents-key-prompt-reset) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents-key-prompt-reset) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-agents-key-wrapup"></a>
## `PUT /api/agents/{key}/wrapup`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveWrapup` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-agents-key-wrapup) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-agents-key-wrapup) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-agents-key-wrapup-reset"></a>
## `POST /api/agents/{key}/wrapup/reset`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgResetWrapup` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-agents-key-wrapup-reset) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents-key-wrapup-reset) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-agents-key-wrapup-task-timeout"></a>
## `PUT /api/agents/{key}/wrapup/task-timeout`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveTaskTimeoutWrapup` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-agents-key-wrapup-task-timeout) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-agents-key-wrapup-task-timeout) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-agents-key-wrapup-task-timeout-reset"></a>
## `POST /api/agents/{key}/wrapup/task-timeout/reset`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgResetTaskTimeoutWrapup` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-agents-key-wrapup-task-timeout-reset) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents-key-wrapup-task-timeout-reset) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-agents-key-triggers"></a>
## `GET /api/agents/{key}/triggers`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListTriggers` · `server/triggers.go` · [handler 근거](evidence:handler-get-api-agents-key-triggers) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents-key-triggers) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-agents-key-triggers"></a>
## `POST /api/agents/{key}/triggers`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgCreateTrigger` · `server/triggers.go` · [handler 근거](evidence:handler-post-api-agents-key-triggers) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents-key-triggers) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-agents-key-prompts"></a>
## `GET /api/agents/{key}/prompts`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListPromptVersions` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-agents-key-prompts) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents-key-prompts) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-agents-key-variables"></a>
## `GET /api/agents/{key}/variables`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgPromptVars` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-agents-key-variables) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents-key-variables) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-agents-key-prompt-preview"></a>
## `POST /api/agents/{key}/prompt/preview`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgPreviewPrompt` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-agents-key-prompt-preview) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-agents-key-prompt-preview) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-agents-key-visibility"></a>
## `GET /api/agents/{key}/visibility`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgGetAgentVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-agents-key-visibility) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-agents-key-visibility) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-put-api-agents-key-visibility"></a>
## `PUT /api/agents/{key}/visibility`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSetAgentVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-agents-key-visibility) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-agents-key-visibility) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-tools"></a>
## `GET /api/tools`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListTools` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-tools) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-tools) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-put-api-tools-key"></a>
## `PUT /api/tools/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgUpdateTool` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-tools-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-tools-key) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-tools-custom"></a>
## `POST /api/tools/custom`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgCreateCustomTool` · `server/customtool.go` · [handler 근거](evidence:handler-post-api-tools-custom) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 409, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-tools-custom) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-tools-custom-test"></a>
## `POST /api/tools/custom/test`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgTestCustomTool` · `server/customtool.go` · [handler 근거](evidence:handler-post-api-tools-custom-test) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-tools-custom-test) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-tools-custom-key"></a>
## `PUT /api/tools/custom/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgUpdateCustomTool` · `server/customtool.go` · [handler 근거](evidence:handler-put-api-tools-custom-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-tools-custom-key) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-tools-custom-key"></a>
## `DELETE /api/tools/custom/{key}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteCustomTool` · `server/customtool.go` · [handler 근거](evidence:handler-delete-api-tools-custom-key) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-tools-custom-key) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-tools-key-reset"></a>
## `POST /api/tools/{key}/reset`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgResetTool` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-tools-key-reset) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `key` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-tools-key-reset) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-mcp"></a>
## `GET /api/mcp`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListMCP` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-mcp) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-mcp) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-mcp"></a>
## `POST /api/mcp`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveMCP` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-mcp) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-mcp) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-mcp-id"></a>
## `DELETE /api/mcp/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteMCP` · `server/server_mgmt.go` · [handler 근거](evidence:handler-delete-api-mcp-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-mcp-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-mcp-id-tools"></a>
## `GET /api/mcp/{id}/tools`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgMCPTools` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-mcp-id-tools) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-mcp-id-tools) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-mcp-id-refresh"></a>
## `POST /api/mcp/{id}/refresh`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgRefreshMCP` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-mcp-id-refresh) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500, 502, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-mcp-id-refresh) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · remote MCP discovery/refresh가 포함될 수 있으며 HTTP response가 해당 호출 완료 경계 |

<a id="op-get-api-skills"></a>
## `GET /api/skills`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsListSkills` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-skills) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-skills) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-skills"></a>
## `POST /api/skills`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsCreateSkill` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-skills) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `201, 400, 401, 409, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-skills) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-skills-upload"></a>
## `POST /api/skills/upload`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsUploadSkill` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-skills-upload) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `overwrite` · body `multipart/form-data` |
| status/error | 직접 관찰 `201, 400, 401, 409, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-skills-upload) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-skills-name"></a>
## `DELETE /api/skills/{name}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsDeleteSkill` · `server/server_mgmt.go` · [handler 근거](evidence:handler-delete-api-skills-name) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-skills-name) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-skills-missing"></a>
## `GET /api/skills/missing`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsMissingSkills` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-skills-missing) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `limit` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-skills-missing) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-skills-name-usage"></a>
## `GET /api/skills/{name}/usage`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsSkillUsage` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-skills-name-usage) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `limit` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-skills-name-usage) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-put-api-skills-name-meta"></a>
## `PUT /api/skills/{name}/meta`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsUpdateSkillMeta` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-skills-name-meta) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-skills-name-meta) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-skills-name-dirs"></a>
## `POST /api/skills/{name}/dirs`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsCreateDir` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-skills-name-dirs) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `-` · body `JSON` |
| status/error | 직접 관찰 `201, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-skills-name-dirs) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-skills-name-files"></a>
## `GET /api/skills/{name}/files`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsListFiles` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-skills-name-files) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-skills-name-files) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-skills-name-files-file"></a>
## `GET /api/skills/{name}/files/{file...}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsReadFile` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-skills-name-files-file) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name, file` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-skills-name-files-file) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-put-api-skills-name-files-file"></a>
## `PUT /api/skills/{name}/files/{file...}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsWriteFile` · `server/server_mgmt.go` · [handler 근거](evidence:handler-put-api-skills-name-files-file) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name, file` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-put-api-skills-name-files-file) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-skills-name-files-file"></a>
## `DELETE /api/skills/{name}/files/{file...}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `fsDeletePath` · `server/server_mgmt.go` · [handler 근거](evidence:handler-delete-api-skills-name-files-file) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name, file` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-skills-name-files-file) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-visibility-kind-id"></a>
## `GET /api/visibility/{kind}/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgResourceVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-visibility-kind-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `kind, id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-visibility-kind-id) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-visibility-toggle"></a>
## `POST /api/visibility/toggle`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgToggleVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-visibility-toggle) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-visibility-toggle) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-visibility-skill-name"></a>
## `GET /api/visibility/skill/{name}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSkillVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-visibility-skill-name) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `name` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-visibility-skill-name) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-visibility-skill-toggle"></a>
## `POST /api/visibility/skill/toggle`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgToggleSkillVisibility` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-visibility-skill-toggle) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-visibility-skill-toggle) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-llm-profiles"></a>
## `GET /api/llm/profiles`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListProfiles` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-llm-profiles) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-profiles) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-llm-profiles"></a>
## `POST /api/llm/profiles`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveProfile` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-llm-profiles) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm-profiles) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-llm-profiles-id"></a>
## `DELETE /api/llm/profiles/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgDeleteProfile` · `server/server_mgmt.go` · [handler 근거](evidence:handler-delete-api-llm-profiles-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 409, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-llm-profiles-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-llm-profiles-active"></a>
## `POST /api/llm/profiles/active`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgActivateProfile` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-llm-profiles-active) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-llm-profiles-active) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-llm-retry-policy"></a>
## `GET /api/llm/retry-policy`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgGetLLMRetryPolicy` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-llm-retry-policy) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-retry-policy) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-llm-retry-policy"></a>
## `POST /api/llm/retry-policy`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgSaveLLMRetryPolicy` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-llm-retry-policy) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm-retry-policy) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-llm-pool"></a>
## `GET /api/llm/pool`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgLLMPoolStatus` · `server/server_mgmt.go` · [handler 근거](evidence:handler-get-api-llm-pool) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-llm-pool) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-llm-pool-reset"></a>
## `POST /api/llm/pool/reset`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgLLMPoolReset` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-llm-pool-reset) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm-pool-reset) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-llm-models"></a>
## `POST /api/llm/models`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `pgListModels` · `server/server_mgmt.go` · [handler 근거](evidence:handler-post-api-llm-models) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-llm-models) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-conversations-id-side-questions"></a>
## `GET /api/conversations/{id}/side-questions`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `handleSideQuestions` · `server/side_questions.go` · [handler 근거](evidence:handler-get-api-conversations-id-side-questions) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `before` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-conversations-id-side-questions) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · history/current snapshot 조회가 응답 전에 끝남; `before`는 invalid/missing이면 0으로 처리 |

<a id="op-post-api-conversations-id-side-questions"></a>
## `POST /api/conversations/{id}/side-questions`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `handleSideQuestions` · `server/side_questions.go` · [handler 근거](evidence:handler-post-api-conversations-id-side-questions) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 202, 400, 401, 404, 409, 429, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-conversations-id-side-questions) |
| 반복·완료 | 같은 client_request_id+question은 기존 request를 200으로 반환; 같은 ID의 다른 question은 409 · side-question session/request 시작; events/terminal request state가 완료 기준 |

<a id="op-delete-api-conversations-id-side-questions"></a>
## `DELETE /api/conversations/{id}/side-questions`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `handleSideQuestions` · `server/side_questions.go` · [handler 근거](evidence:handler-delete-api-conversations-id-side-questions) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-delete-api-conversations-id-side-questions) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · active run에 cancel을 요청하고 DB history clear 후 응답; run goroutine 종료까지 기다리지는 않음 |

<a id="op-get-api-side-questions-requestid-events"></a>
## `GET /api/side-questions/{requestID}/events`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `sideEvents` · `server/side_questions.go` · [handler 근거](evidence:handler-get-api-side-questions-requestid-events) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `requestID` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-side-questions-requestid-events) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · SSE 연결 수립; event lifecycle은 stream별 cursor/메모리 상태를 확인 |

<a id="op-post-api-side-questions-requestid-cancel"></a>
## `POST /api/side-questions/{requestID}/cancel`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `cancelSideRequest` · `server/side_questions.go` · [handler 근거](evidence:handler-post-api-side-questions-requestid-cancel) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `requestID` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-side-questions-requestid-cancel) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · side-question session/request 시작; events/terminal request state가 완료 기준 |

<a id="api-page-limit"></a>
## 이 페이지의 확인 한계

- route registration/auth/handler 직접 목적지는 전수 확인했다.
- field/schema/error/side-effect 의미는 별도 schema page의 C/P/U가 권위다.
- OpenAPI가 없고 실제 HTTP server는 실행하지 않았다. helper 내부·외부 서비스·DB 운영 상태는 정적 소스 이상으로 보장하지 않는다.
