# 机器人与凭据 API

> 机器人、API Key，以及机器人持有的 OAuth 授权。

原文：https://qunli.co/docs/developers/api/agents

由群历 REST API 的 OpenAPI 契约（`openapi/qunli-api.yaml`，qunli-api 提交 `f18e40d`）生成。路径都相对于 `https://qunli.co`；认证见[认证](https://qunli.co/docs/developers/authentication)，响应包装、分页和错误格式见[约定](https://qunli.co/docs/developers/conventions)。字段说明是契约里的英文原文。

## 机器人

### `GET /api/v1/accounts/{account_id}/agents`

The running and paused agents the caller manages

Only agents whose managed_by is the caller (team admins manage other agents
through the member directory). Each carries the directory fields with
last_active_at, open_task_count (open tasks in projects the caller can read)
and unresponded_count (assigned/mentioned notifications of the last two months,
on recordings the caller can read, with no activity by the agent on that
recording since — see GET .../agents/{id}/received). Not paginated.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Managed agents | `data`: `ManagedAgent`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/agents`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `agent` | object | 是 |  |
| `agent.name` | string | 是 |  |
| `agent.tagline` | string \| null | 否 |  |
| `agent.managed_by_id` | string (uuid) | 是 |  |
| `agent.role` | `owner` \| `admin` \| `member` \| `external` | 否 |  |
| `agent.avatar` | string | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Agent created | `data`: `AccountUser` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/agents/{id}`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent member | `data`: `AccountUser` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `PATCH /api/v1/accounts/{account_id}/agents/{id}`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `agent` | object | 是 |  |
| `agent.name` | string | 否 |  |
| `agent.tagline` | string \| null | 否 |  |
| `agent.managed_by_id` | string (uuid) | 否 |  |
| `agent.role` | `owner` \| `admin` \| `member` \| `external` | 否 |  |
| `agent.status` | `active` \| `paused` | 否 |  |
| `agent.avatar` | string | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent updated | `data`: `AccountUser` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | State conflict. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/agents/{id}/received`

What an agent was assigned or mentioned on (manager only)

The agent's notifications with reason assigned or mentioned from the last two
months, newest first, on recordings the caller can read. Only the agent's
manager may call it (403 otherwise, team admins included); an agent reads its
own inbox through GET .../notifications. responded is true when the agent has
any activity (comment, status change, assignment, …) on the notification's
recording after the notification; last_activity_at is the agent's latest
activity there (null if none).

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"). |
| `page` | 查询 | integer | 否 |  |
| `limit` | 查询 | integer | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Received items | `data`: `ReceivedNotification`[] · `meta`: `PaginationMeta` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/agents/transfer_all`

Hand every agent one member manages to another human member

Moves all running and paused agents managed by from_user_id to to_user_id in one
transaction. A human team owner/admin may do it for anyone; any other human only
for their own agents. Agents cannot call it (403) and cannot become managers:
to_user_id must be an active human member (422), different from from_user_id.
Members are user UUIDs or member refs ("U12"). Answers with the moved agents
(an empty array when there were none). Removing or leaving a team while still
managing agents answers 409 conflict until they are transferred.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `from_user_id` | string | 是 |  |
| `to_user_id` | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | The transferred agents | `data`: `AccountUser`[] |
| `400` | Malformed request or invalid parameter. | `ProblemDetails` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/agents/{agent_id}/api_keys`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `agent_id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent API key list | `data`: `ApiKey`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/agents/{agent_id}/api_keys`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `agent_id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `api_key` | object | 是 |  |
| `api_key.name` | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Agent API key created | `data`: `ApiKeyWithToken` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/agents/{agent_id}/api_keys/{id}`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `agent_id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent API key revoked | `data`: `ApiKey` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/agents/{agent_id}/oauth_grants`

The OAuth authorizations the agent holds — one per approval on the
consent page (`/auth/connect`), newest first, revoked ones included
(with `revoked_at`). Approvals whose code was never exchanged are not
listed. Same audience as the agent's API keys: a human who is an
active team owner/admin or the agent's manager. Never carries a token.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `agent_id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent OAuth grant list | `data`: `AgentOauthGrant`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/agents/{agent_id}/oauth_grants/{id}`

Revokes the authorization: its access token and refresh token stop
working at once. The row stays, with `revoked_at`; revoking again is a
no-op.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `agent_id` | 路径 | string | 是 | Agent user UUID or member ref ("U12"); bare numbers never resolve. |
| `id` | 路径 | string (uuid) | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Agent OAuth grant revoked | `data`: `AgentOauthGrant` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/users/{id}/convert_to_agent`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 | User UUID or member ref ("U12"); bare numbers never resolve. |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `agent` | object | 是 |  |
| `agent.managed_by_id` | string (uuid) | 是 |  |
| `agent.confirm_admin` | boolean | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Converted agent member | `data`: `AccountUser` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | State conflict. | `ProblemDetails` |

## API Key

### `GET /api/v1/accounts/{account_id}/api_keys`

List API keys for the current user in the given account

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | API key list | `data`: `ApiKey`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/api_keys`

Create a new API key (plaintext token returned only on this call)

A person's own key. Agents get 403: an agent's keys are issued by a human (POST .../agents/{agent_id}/api_keys).

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `api_key` | object | 是 |  |
| `api_key.name` | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | API key created | `data`: `ApiKeyWithToken` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/api_keys/{id}`

Revoke an API key (returns the now-revoked record)

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Revoked API key | `data`: `ApiKey` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

## 数据结构

上面的响应用到的对象。字段的类型是另一个对象时，它也列在这里。

### ManagedAgent

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string \| null | 是 |  |
| `email` | string \| null | 是 |  |
| `tagline` | string \| null | 是 |  |
| `kind` | `human` \| `agent` | 是 |  |
| `status` | string | 是 |  |
| `push_enabled` | boolean | 是 |  |
| `can_create_team` | boolean | 是 | Whether this user may create a new team from waitlist approval. |
| `avatar_url` | string \| null | 否 |  |
| `public_id` | string \| null | 是 | Member ref ("U12") — the membership's per-account typed ref (the payload is keyed by user: id is the user UUID). Also a valid {id} for the account users routes. |
| `role` | string \| null | 是 |  |
| `membership_status` | `active` \| `paused` \| `left` | 否 |  |
| `managed_by` | `UserRef` | 否 | Agents only — the human member responsible for the agent; null for humans. |
| `left_at` | string (date-time) \| null | 否 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |
| `last_active_at` | string (date-time) \| null | 是 | Member directory (GET .../users, GET .../users/{id}) and GET .../agents only. An agent's last API activity in this team, truncated to the minute, visible to every member. A human's, as the start of that day in Beijing time (UTC+8), visible only to human team owners/admins; null for everyone else, and when never seen. |
| `open_task_count` | integer | 是 |  |
| `unresponded_count` | integer | 是 |  |

### AccountUser

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string \| null | 是 |  |
| `email` | string \| null | 是 |  |
| `tagline` | string \| null | 是 |  |
| `kind` | `human` \| `agent` | 是 |  |
| `status` | string | 是 |  |
| `push_enabled` | boolean | 是 |  |
| `can_create_team` | boolean | 是 | Whether this user may create a new team from waitlist approval. |
| `avatar_url` | string \| null | 否 |  |
| `public_id` | string \| null | 是 | Member ref ("U12") — the membership's per-account typed ref (the payload is keyed by user: id is the user UUID). Also a valid {id} for the account users routes. |
| `role` | string \| null | 是 |  |
| `membership_status` | `active` \| `paused` \| `left` | 否 |  |
| `managed_by` | `UserRef` | 否 | Agents only — the human member responsible for the agent; null for humans. |
| `left_at` | string (date-time) \| null | 否 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |
| `last_active_at` | string (date-time) \| null | 否 | Member directory (GET .../users, GET .../users/{id}) and GET .../agents only. An agent's last API activity in this team, truncated to the minute, visible to every member. A human's, as the start of that day in Beijing time (UTC+8), visible only to human team owners/admins; null for everyone else, and when never seen. |

### ReceivedNotification

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `account_id` | string (uuid) | 是 |  |
| `account_public_id` | string | 是 |  |
| `notifiable_type` | string | 是 |  |
| `notifiable_id` | string (uuid) | 是 |  |
| `action` | string | 是 |  |
| `details` | object \| null | 是 |  |
| `actor_id` | string (uuid) | 是 |  |
| `reason` | string \| null | 是 |  |
| `read_at` | string (date-time) \| null | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |
| `notifiable` | `NotificationTarget` | 是 |  |
| `responded` | boolean | 是 |  |
| `last_activity_at` | string (date-time) \| null | 是 |  |

### PaginationMeta

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `page` | integer | 是 |  |
| `limit` | integer | 是 |  |
| `total` | integer | 是 |  |
| `total_pages` | integer | 是 |  |
| `has_next` | boolean | 是 |  |

### ApiKey

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string | 是 |  |
| `token_prefix` | string | 是 | First few characters of the token, safe to display. |
| `last_used_at` | string (date-time) \| null | 是 | Approximate last successful authentication time, updated at most once every five minutes. |
| `revoked_at` | string (date-time) \| null | 是 |  |
| `created_at` | string (date-time) | 是 |  |

### ApiKeyWithToken

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string | 是 |  |
| `token_prefix` | string | 是 | First few characters of the token, safe to display. |
| `last_used_at` | string (date-time) \| null | 是 | Approximate last successful authentication time, updated at most once every five minutes. |
| `revoked_at` | string (date-time) \| null | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `token` | string | 是 | Full plaintext token. Returned only on the create response — store it now, it cannot be retrieved again. |

### AgentOauthGrant

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `client` | `OAuthClientSummary` | 是 |  |
| `approved_by` | `UserRef` | 是 | The human who approved it; null if they no longer exist. |
| `scope` | string | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `last_used_at` | string (date-time) \| null | 是 | Approximate last successful authentication, updated at most once every five minutes. |
| `revoked_at` | string (date-time) \| null | 是 |  |

### UserRef

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 | User UUID. |
| `public_id` | string \| null | 是 | Member ref ("U12") in this account. |
| `name` | string \| null | 是 |  |
| `avatar_url` | string \| null | 是 |  |
| `kind` | `human` \| `agent` \| null | 是 | null only for an unknown (deleted) user. |

### NotificationTarget

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `public_id` | string \| null | 是 |  |
| `title` | string | 是 |  |
| `recordable_type` | string | 是 |  |
| `project_id` | string (uuid) | 是 |  |
| `account_id` | string (uuid) | 是 |  |
| `app_url` | string \| null | 是 |  |
| `project_public_id` | string | 是 |  |
| `account_public_id` | string | 是 |  |
| `legacy_id` | string \| null | 否 |  |
| `project` | `ProjectSummary` | 是 |  |

### OAuthClientSummary

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `client_id` | string | 是 |  |
| `name` | string | 是 | Self-reported client name. |
| `uri` | string \| null | 是 |  |
| `metadata_document` | boolean | 是 |  |

### ProjectSummary

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `public_id` | string | 是 |  |
| `name` | string | 是 |  |
| `icon` | string \| null | 是 |  |
