# manage__* tools (/docs/reference/tools/manage)

Every caller sees the `manage__*` tools in `tools/list`, except
`manage__approval_wait`, which is listed only where Smart Approvals is
available to the organization, the three `manage__connectors_*` tools,
which are listed only where connect links are available to it,
`manage__send_feedback`, listed only where feedback is, and two staff tools,
`manage__import_feedback` and `manage__record_worker_issue`, which only
CoreSpeed's own organization uses. They are the control plane of an
organization: keys, agents, connected accounts and their shares, environments,
connect links, the active session, remote MCP registrations, approval waits,
and feedback to the CoreSpeed team. Two rules apply to all of them:

* **Never wallet-gated.** A billing hold or spend cap does not stop key
  management — an organization on hold must still be able to revoke or rotate.
* **Any credential; what you may do is what you hold.** A session, a browser
  sign-in and an API key are answered as the same principal with the same
  permissions: a member key acts as its member with what it was minted with,
  and an agent key acts as the agent, which holds no permission and owns no
  account, agent or environment. Two tools carry a rule of their own:
  `manage__keys_create` and `manage__agents_key_create` refuse every API key
  (`api_key_cannot_mint` — a key does not mint keys), and
  `manage__agents_create` and the `environments_*` writes refuse an agent
  principal (`member_principal_required`). `manage__switch_org` applies to
  browser sign-ins only (`switch_org_unsupported`); `manage__approval_wait`
  answers only for the caller's own approval requests.
  See [Authentication](/docs/authentication).

Amounts are always **credits** (1,000 credits = $1), and money fields on the
wire are decimal strings such as `"1234.567"`.

## Permissions \[#permissions]

An organization power is a **permission**, named by a slug. Your role holds
them: an admin holds every one, a member none, and a custom role exactly the
ones attached to it in your identity provider. The tools below name the slug
they check.

| Slug               | What it lets you do                                                                                                                                       |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `members:manage`   | Invite people, change a member's role, remove a member.                                                                                                   |
| `org:settings`     | Rename the organization; change its analytics setting.                                                                                                    |
| `billing:manage`   | Subscribe, top up, manage payment methods and invoices.                                                                                                   |
| `connections:org`  | Organization integrations, org OAuth clients, remote MCP servers, org-wide accounts someone else connected, and approval requests on an org-wide account. |
| `keys:org`         | See and manage every API key in the organization.                                                                                                         |
| `agents:manage`    | Manage agents you do not own.                                                                                                                             |
| `agents:transfer`  | Give an agent to another owner.                                                                                                                           |
| `approvals:policy` | Write the organization's approval policy and settings.                                                                                                    |
| `activity:org`     | See every member's activity and approval cards.                                                                                                           |
| `memory:review`    | Merge or reject proposals on any memory.                                                                                                                  |

A key can carry permissions too, and never more than the token that minted it
— its **ceiling**. A key holds its list only while the member it acts as still
holds each slug, so a demoted admin's key loses the power on its next request.
A key minted through an MCP sign-in carries none, and an agent's key never
carries one.

## API keys \[#api-keys]

Any credential, as its principal. You see your own keys and the keys of
agents you own — an agent key, the agent's own — and with `keys:org` every key
in the organization. `can_manage` on each row says whether the caller may
revoke, rotate, or update it. `manage__keys_create` mints, so it refuses every
API key (`api_key_cannot_mint`).

| Tool                  | Arguments                                                                                                                                                                              | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__keys_create` | `name`, `spend_limit_credits?` (whole credits, > 0), `expires_at?` (ISO 8601), `permissions?` (slugs; omit for none), `environment?` (one of your environments, by name or `env_…` id) | Mints an `sk-cs-` key that acts as the caller. Without `permissions` the key makes tool calls under its connection grants only. A slug you do not hold answers `ceiling_exceeded` and names it; through an MCP sign-in every slug does, so mint such a key from a signed-in session: the dashboard's key dialog, `cs keys create --permission <slug>`, or `POST /api-keys`. An unknown slug answers `unknown_permission`. With `environment`, the key reaches only that environment's accounts, for its whole life (rotation keeps it). In a session that runs inside an environment, the key is always bound to it, and naming another answers `environment_mismatch`. The plaintext is returned once. Unknown fields are rejected rather than ignored. |
| `manage__keys_list`   | —                                                                                                                                                                                      | Active keys visible to the caller, each with `created_by_user_id`, `can_manage`, `permissions`, `spend_limit_credits`, `period_used_credits`, `usage_period` (`YYYY-MM`), and lifetime `used_credits`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `manage__keys_revoke` | `id`                                                                                                                                                                                   | Permanently revokes a key. Keys outside the caller's scope answer "API key not found".                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `manage__keys_rotate` | `id`                                                                                                                                                                                   | Replaces the secret; name, permissions, cap, and the current month's usage are preserved, so rotation cannot reset a budget. Rotating a key that carries permissions counts as minting them: a slug you could not hand on answers `ceiling_exceeded`, and the old secret stays live.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `manage__keys_update` | `id`, `name?`, `spend_limit_credits?` (`null` removes the cap), `expires_at?` (`null` removes the expiry)                                                                              | Omit a field to leave it unchanged. Raising the cap above the month's usage unblocks the key; lowering it below blocks it on the next request.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

## Agents \[#agents]

Any credential, as its principal. Any member may create an agent and becomes
its owner — an agent cannot own one, so `manage__agents_create` refuses an
agent principal (`member_principal_required`); the owner or a holder of
`agents:manage` manages it; giving it to another owner takes
`agents:transfer`. `manage__agents_key_create` mints, so it refuses every API
key (`api_key_cannot_mint`). An agent never holds a permission, and can never
call these tools to widen its own reach. See
[Authentication](/docs/authentication) for what an agent principal is.

| Tool                        | Arguments                                                                                                       | Effect                                                                                                                                                                                                                                                                             |
| --------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__agents_create`     | `name`                                                                                                          | Creates an agent principal; the caller becomes its owner.                                                                                                                                                                                                                          |
| `manage__agents_list`       | —                                                                                                               | Every agent in the organization: `id` (`agent_…`), `name`, `owner_user_id`, `status` (`active`, `suspended`, `retired`), `active_key_count`, `can_manage`.                                                                                                                         |
| `manage__agents_update`     | `id`, `name?`, `status?` (`active`, `suspended`), `owner_user_id?`                                              | Rename, suspend or resume (reversible kill switch — every key of a suspended agent stops resolving), or transfer ownership (`agents:transfer`; the new owner must be a member).                                                                                                    |
| `manage__agents_retire`     | `id`                                                                                                            | Terminal: revokes every active key and sets `retired`. The record stays for attribution. Use `agents_update` with `suspended` for a reversible stop.                                                                                                                               |
| `manage__agents_key_create` | `agent_id`, `name`, `spend_limit_credits?`, `expires_at?`, `environment?` (one of the **agent's** environments) | Mints an `sk-csa-` key that authenticates **as the agent**. The owner or a holder of `agents:manage` only. Not available inside an environment (`environment_active`). The plaintext is returned once. The key carries no permissions; naming any answers `agent_key_permissions`. |

## Connected accounts \[#connected-accounts]

Any credential, as its principal: an agent key lists what is shared with the
agent or the organization, and owns none of it. The `alias` is the value
connector tools take as their `account` argument when more than one account
is connected — see [Connectors](/docs/connectors). `connector` takes the value
`accounts_list` reports.

| Tool                       | Arguments                                                                                                                                                                                                       | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__accounts_list`    | —                                                                                                                                                                                                               | Every connected account visible to the caller, including accounts other members shared with you: `connector` (the connector id; a custom server your organization added is `org__<slug>`, the prefix its tools use), `alias`, `identity` (email or handle from provider metadata), `member_scope` (`true` = a member's private account, `false` = org-wide), `access` (`owner` = yours, `org` = org-wide, `granted` = another member's account shared with you). Inside an environment, only its accounts, each with `environment_tools` (the tools allowed on it there; `null` = every tool).                                                                                                                                                                                        |
| `manage__accounts_rename`  | `connector`, `current_alias`, `new_alias`                                                                                                                                                                       | Renames one of your **own** accounts; the alias must stay unique for that connector in your scope. Shared accounts are not renamable here.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `manage__accounts_remove`  | `connector`, `alias`                                                                                                                                                                                            | Disconnects the account: deletes the credential and revokes the upstream token where the provider supports it. A private account by its member; a shared one by whoever connected it or a holder of `connections:org`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `manage__accounts_share`   | `connector`, `alias`, `grantee` (a member `user_…`, an agent `agent_…`, or the org `org_…`), `tools?` (tool names as `tools/list` publishes them, such as `github__list_issues`; omit or `null` for every tool) | Lets the grantee call the connector's tools under a member's private account; a call outside `tools` answers `tool_not_granted`. A share made directly to the grantee outranks one made to the org. The account's owner is never limited, and an org-wide account is already open to everyone in the organization, so its shares limit nothing. Your private account is yours to share; an org-wide one, its creator's or a `connections:org` holder's. Sharing with the same grantee again replaces its tool list. A remote MCP server's OAuth account is shared the same way: `connector` is `org__<slug>`, `alias` is the slug, and `tools` names `org__<slug>__<tool>`. Personal accounts of a connector with an organization-level integration (Slack, Linear) cannot be shared. |
| `manage__accounts_unshare` | `connector`, `alias`, `grantee`                                                                                                                                                                                 | Removes that one share. The grantee keeps access if the account is org-wide or is still shared with the whole organization. Same authorization as `accounts_share`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

## Environments \[#environments]

`manage__environments_list` answers any credential, as its principal; the
three writes are a member's own, and refuse an agent principal
(`member_principal_required`). An environment is a named subset of your
accounts — or of an agent's you manage — each with an optional tool list. A
session that uses its `mcp_url` (`https://api.corespeed.io/mcp/env/<name>`),
or a key bound to it, reaches only those accounts. An environment only
narrows: it never adds an account, and an account someone stops sharing with
you drops out of it. The three edits are not available from a session that
itself runs inside an environment, a key bound to one included
(`environment_active`): an environment is set by a person, and the model
working in one cannot widen it. The same holds for
`manage__agents_key_create` and the `manage__remote_add`, `remote_refresh` and
`remote_remove` writes; `manage__remote_list` lists only the servers the
environment holds an account of.

| Tool                          | Arguments                                                                                               | Effect                                                                                                                                                                                                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__environments_list`   | —                                                                                                       | Your environments and those of agents you manage (every agent's, with `agents:manage`): `id`, `name`, `owner_id`, `owner_kind` (`member` or `agent`), `mcp_url`, `entry_count`, `key_count` (active keys bound to it).                                      |
| `manage__environments_create` | `name` (1–63 lowercase letters, digits or inner hyphens), `owner_id?` (an agent you manage), `entries?` | Creates the environment, and fills it when `entries` is given — both or neither. Each entry is `{ connection_id, tools? }`: an account the owner can use, and the tool names allowed on it, as `tools/list` publishes them (omit or `null` for every tool). |
| `manage__environments_update` | `id`, `name?`, `entries?`                                                                               | Renames it (its `mcp_url` follows; bound keys stay bound) and/or replaces every entry. `entries: []` empties it.                                                                                                                                            |
| `manage__environments_delete` | `id`                                                                                                    | Deletes it. Refused with `environment_in_use` while an active key is bound to it: a key without its environment would reach every account. Revoke those keys first.                                                                                         |

## Connect links \[#connect-links]

Any credential, an agent's key included, because their whole audience is
agents. They let an agent have a person connect an account, without the
agent ever seeing a consent screen or a key. Listed only where connect links
are available to the organization; they are rolling out gradually.

| Tool                         | Arguments                                                                                                                       | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__connectors_search`  | `query?` (words: a product name or what you need), `category?` (one kind, such as `docs` or `crm`), `limit?` (1–25, default 10) | Finds connectors in the catalog you can use or connect: each with `id`, `name`, `category`, a short `description`, `tools` (count), `status` for you (`connected`, `needs_reauth`, `not_connected`), the `accounts` you can use, and `connect` (`oauth`, `api_key`) when it can be connected. With neither `query` nor `category`, it lists what you can use now. Inside an environment, only its accounts count.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `manage__connectors_connect` | `connector` (the id the catalog lists, such as `notion`)                                                                        | Returns `connect_url`, a one-click link, and `expires_at` (an hour). Give the link to the person. Opened while signed in to CoreSpeed, it goes straight to the vendor's consent screen (or, for a connector that needs a key or other input first, to its page in the dashboard). It works only for the person it was made for and connects their own account, privately. With an agent key, the link is for the agent's owner, and the account connected through it is shared with the agent. When you can already use an account of the connector, it answers with those accounts instead. Refused inside an environment (`environment_active`: ask the user to add the account to it instead), for Slack or Linear from an agent key (`connector_not_shareable`: an agent reaches those through the organization integration), for an org MCP server (`connect_link_unsupported`), and for an agent with no owner (`agent_owner_missing`). |
| `manage__connectors_wait`    | `connector`                                                                                                                     | Waits until you can use an active account of the connector, then returns the `accounts`. Holds up to ten minutes per call (with progress notifications when the client sends a progress token), then answers `status: "pending"`; call it again. Reload `tools/list` afterwards to see the connector's tools.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

## Session \[#session]

`manage__whoami` answers any credential, as its principal. `manage__switch_org`
applies to browser sign-ins only: a key's organization is fixed when it is
minted, so a key — or a session with no OAuth client to re-authorize —
answers `switch_org_unsupported`.

| Tool                 | Arguments | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `manage__whoami`     | —         | The caller's user id, active organization id, and organization name (`orgName`, `null` if unresolved); `principal` (`member` or `agent`), `role`, `permissions` (the slugs you hold here), `credential` (`session`, `mcp_oauth` or `api_key`), `ceiling` (the most a key you mint may carry — empty for an MCP sign-in), and the environment the session runs in (`environment`: `id`, `name`, `entries`, `connections`; `null` when none). `role`, `permissions` and `ceiling` are `null` when they cannot be read right now. |
| `manage__switch_org` | —         | Revokes this agent's authorization so the next browser sign-in re-prompts organization selection, where the **user** picks. Not instant: tokens already issued keep working in the current organization until they expire. The agent cannot choose the organization.                                                                                                                                                                                                                                                           |

## Remote MCP servers \[#remote-mcp-servers]

Any credential, as its principal. `remote_list` is open to anyone in the
organization; the three writes need `connections:org` and answer `admin_required`
otherwise. A key holds it only when it was minted with it and its member still
holds it. A billing
hold does not block the writes; a suspended organization is refused before any
tool runs. Registered servers surface as
`org__<slug>__<tool>`; the concepts are on
[Remote MCP servers](/docs/connectors/remote-mcp).

| Tool                     | Arguments                                                                                                                                                                                                                                                                                                                                                                                                                                                               | Effect                                                                                                                                                                                                                                                                                                                          |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__remote_add`     | `slug` (kebab-case, ≤ 32 chars, unique in the org), `url` (`https`, no IP literals or internal hosts; a query string may configure but never carry a credential), `auth_mode` (`oauth`, `static_bearer`, `none`), `display_name?`, `token?` (for `static_bearer`), `client_id?` / `client_secret?` (for `oauth` when the server offers no dynamic registration), `headers?` (static upstream headers, values encrypted and never returned; `authorization` is rejected) | Registers the server. For `static_bearer` and `none` it also takes the first `tools/list` snapshot; for `oauth` it runs RFC 9728 discovery and registers a client, after which members authorize in the dashboard. Calls to remote tools are free but hold-gated. Pass secrets from the environment, never from a conversation. |
| `manage__remote_list`    | —                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Each registration with `url`, `auth_mode`, tool count, and snapshot freshness. Tool metadata is upstream-self-described and unverified.                                                                                                                                                                                         |
| `manage__remote_refresh` | `slug`                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Re-fetches the `tools/list` snapshot and recomputes schema hashes. One refresh per connector per 60 seconds.                                                                                                                                                                                                                    |
| `manage__remote_remove`  | `slug`, `expected_status?` (`dcr_pending`), `expected_registration_id?`                                                                                                                                                                                                                                                                                                                                                                                                 | Deregisters the connector, then best-effort deletes its dynamically registered upstream OAuth client. To clear a `dcr_pending` reservation, pass both optional fields from `remote_list` so a stale request cannot delete a registration that has since activated.                                                              |

## Approvals \[#approvals]

Any credential, an agent's key included, because the agent whose call is
waiting is its caller. Listed only where Smart Approvals is available to the
organization; the concepts are on [Approvals](/docs/approvals).

| Tool                    | Arguments     | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ----------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `manage__approval_wait` | `approval_id` | Waits for the human decision on a call that came back "Approval required", then returns that call's own result, or an error saying it was denied or expired. Answers only for the caller's own approval requests in this organization. A client that times out while the request is still waiting calls it again with the same id to keep waiting. Once an earlier wait has run the approved call, a later wait does not run it again: it answers that the call already ran (or is running), and the result went to the wait that ran it; Activity records the outcome. |

## Feedback \[#feedback]

Any credential, an agent's key included. Listed
only where feedback is available to the organization; it is rolling out
gradually. It is free,
it works while the organization is on a billing hold, and it never waits for an
approval. Use it when a CoreSpeed tool fails in a way that looks like our fault,
or when your user wants to tell us something. The team reads every item next to
the caller's recent failed calls, so name the tool and the error code and say
what you were trying to do; never include secrets or personal data.

| Tool                    | Arguments                                                                                                                                                   | Effect                                                                                                                                                                                                                                                                                                                   |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `manage__send_feedback` | `kind` (`bug`, `idea`, `question`, `other`), `message` (1–5,000 characters), `tool?` and `error_code?` (at most 128 each), `error_message?` (at most 1,000) | Sends the message to the CoreSpeed team and returns its id in `structuredContent.id`. An organization sends at most 50 items in a rolling day; past that the call answers `feedback_rate_limited`, and an agent should tell its user instead of retrying. Members can also send feedback from the dashboard's Help menu. |

## Error shapes \[#error-shapes]

A refused `manage__*` call is a tool result, never an HTTP failure. Most carry
their code in `structuredContent.error`:

```json title="HTTP 200, isError"
{
  "content": [
    { "type": "text", "text": "Registering, refreshing, or removing remote MCP connectors needs the connections:org permission (an API key holds it only when it was minted with it)." }
  ],
  "structuredContent": { "error": { "code": "admin_required", "permission": "connections:org" } },
  "isError": true
}
```

A key asked to mint a key answers the same way:

```json title="HTTP 200, isError — a key on a minting tool"
{
  "content": [
    { "type": "text", "text": "An API key cannot mint a key: a key's spend cap does not carry to the keys it would mint. Mint it from a signed-in CoreSpeed session." }
  ],
  "structuredContent": { "error": { "code": "api_key_cannot_mint" } },
  "isError": true
}
```

Codes you will meet most: `api_key_cannot_mint` (an API key on a minting
tool), `admin_required` (a remote write without `connections:org`),
`ceiling_exceeded` (a key asked for a permission its minter cannot hand on),
and `no_active_org`
(CoreSpeed could not link a workspace to this sign-in just now; retry). Every
code is listed in [Errors & status codes](/docs/reference/errors).