> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cominty.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom agents

> Create and manage agents with an API key: capabilities, models, and what the key can see

An API key can create and manage agents, the same way an admin does on the
**Agents** page of [platform.cominty.ai](https://platform.cominty.ai). A custom
agent runs like [Hive](https://docs.cominty.ai/guides/agents.md), with the capabilities, instructions, and
models you give it. Pass its id as the agent id of any chat call.

This page works for the [Python SDK](https://docs.cominty.ai/sdk/overview.md), the
[JavaScript SDK](https://docs.cominty.ai/js-sdk/overview.md), and HTTP. Each snippet has a tab for each.
Both SDKs have the same methods on `client.agents`. The names that differ:

| Name | Python SDK | JavaScript SDK | HTTP |
| - | - | - | - |
| Agent id of a chat | `agent_id` | `agentId` | `options.agent_id` on `POST /chat` |
| List the models | `list_models` | `listModels` | `GET /agents/models` |
| Set the model chain | `set_models` | `setModels` | `PUT /agents/{agent_pid}/models` |
| Model ids | `model_ids` | `modelIds` | `model_ids` |
| Override flag | `allow_execution_options_override` | `allowExecutionOptionsOverride` | `allow_execution_options_override` |

## What an API key can do

The key acts as an **admin of its own organization**. This frames every
resource of this guide, and of [Skills](https://docs.cominty.ai/guides/skills.md) and
[Sources](https://docs.cominty.ai/guides/sources.md).

| The key can | The key cannot |
| - | - |
| Create agents and skills for the whole organization (scope `organization`) | See another member's **private** agents, skills, or drives. They are absent from lists, and a read by id returns 404. |
| Read the model catalog and set an agent's model chain | See agents created on the other product surface. A Platform key does not see Portal agents. |
| Create sources from local files | Create a Google Drive or SharePoint source. They need the console's OAuth flow. |

Everything the key creates is **owned by the user who created the key**. The
agent's `owner` is that user's id, not the key's. Call that user the key owner.

> [!WARNING]
>
> A key is powerful. It can edit and delete the organization's agents, and it
> can change a built-in agent's model chain for every user. Store it like a
> password.

## Find the values you need

An agent refers to integrations and models by id. Read them from the API.

> [tab] Python SDK
>
> ```python theme={null}
> servers = await client.mcp.list()          # integrations that are turned on
> models = await client.agents.list_models() # models you can chain
>
> print([server.name for server in servers])  # ['datagouv', 'linear', ...]
> print(repr(models[0]))                      # LLMModelSummaryOut(id='...', name='...')
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> const servers = await client.mcp.list()        // integrations that are turned on
> const models = await client.agents.listModels() // models you can chain
>
> console.log(servers.map((server) => server.name)) // ['datagouv', 'linear', ...]
> console.log(models[0])                            // { id: '...', name: '...' }
> ```

> [tab] HTTP
>
> ```bash theme={null}
> curl "https://ds.cominty.com/mcp/manifest" \
>   -H "x-cominty-token: $COMINTY_API_KEY"
>
> curl "https://ds.cominty.com/agents/models" \
>   -H "x-cominty-token: $COMINTY_API_KEY"
> ```

* A server's `name` is the value to store in the `connections` of the MCP
  capability. By default, `mcp.list()` keeps only the integrations that are
  turned on. Set `enabled` to null to see every server. See `client.mcp` in the
  [Python SDK](https://docs.cominty.ai/sdk/reference.md#client-mcp) and
  [JavaScript SDK](https://docs.cominty.ai/js-sdk/reference.md#client-mcp) references.
* `requires_oauth_connect` is true when someone must connect the integration
  with OAuth in the console first. See [MCP integrations](https://docs.cominty.ai/mcp/overview.md).
* A model's `id` goes in the agent's model chain.

## Create an agent

> [tab] Python SDK
>
> ```python theme={null}
> from cominty_sdk import AgentCapabilities, McpCapability, WebCapability
>
> agent = await client.agents.create(
>     name="Linear helper",
>     description="Created through the API key",
>     instructions="Use your Linear tools when asked about Linear. Be brief.",
>     scope="organization",
>     capabilities=AgentCapabilities(
>         mcp=McpCapability(activation="always", connections=["linear"]),
>         web=WebCapability(activation="never"),
>     ),
>     model_ids=[models[0].id],
> )
> print(agent.id, agent.owner)
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> let agent = await client.agents.create({
>     name: 'Linear helper',
>     description: 'Created through the API key',
>     instructions: 'Use your Linear tools when asked about Linear. Be brief.',
>     scope: 'organization',
>     capabilities: {
>         mcp: { activation: 'always', connections: ['linear'] },
>         web: { activation: 'never' },
>     },
>     modelIds: [models[0]!.id],
> })
> console.log(agent.id, agent.owner)
> ```

> [tab] HTTP
>
> ```bash theme={null}
> curl -X POST "https://ds.cominty.com/agents" \
>   -H "x-cominty-token: $COMINTY_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "name": "Linear helper",
>     "description": "Created through the API key",
>     "instructions": "Use your Linear tools when asked about Linear. Be brief.",
>     "scope": "organization",
>     "capabilities": {
>       "mcp": {"activation": "always", "connections": ["linear"]},
>       "web": {"activation": "never"}
>     },
>     "model_ids": ["MODEL_ID"]
>   }'
> ```

The reply is the full agent:

```json theme={null}
{
  "id": "xK3mPq9RzT2v",
  "name": "Linear helper",
  "description": "Created through the API key",
  "capabilities": {
    "web": {"activation": "never"},
    "mcp": {"activation": "always", "connections": ["linear"]},
    "memory": {"activation": "never"}
  },
  "managed": false,
  "scope": "organization",
  "owner": "user_31HPTBuBvX20xlQNAbvxjOxPbKB",
  "instructions": "Use your Linear tools when asked about Linear. Be brief.",
  "allow_execution_options_override": false,
  "models": [{"id": "MODEL_ID", "name": "..."}]
}
```

* `scope` is `"private"` (the key owner only, the default) or
  `"organization"` (every member).
* A capability you do not set gets its default, here `memory: never`. Over HTTP,
  the capabilities you did not set come back as `null`. The SDKs leave them out.
* Omit the model ids to use the organization's default model chain.
* `capabilities.memory` sets the agent's memory namespace. The older
  `execution_options` and `memory_namespace` fields are deprecated, and the SDKs
  do not accept them.
* Capabilities work as on a thread. See [Capabilities](https://docs.cominty.ai/guides/capabilities.md).
  The agent's capabilities are the saved default of the first of the
  [three layers](https://docs.cominty.ai/guides/capabilities.md#three-layers).

## Chat with it

Use the id like any other agent.

> [tab] Python SDK
>
> ```python theme={null}
> run = await client.chat.start(
>     agent_id=agent.id,
>     message="Use your Linear tools to list my Linear teams.",
> )
> message = await run.result()
> print(message.status.value, "|", message.content)
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> const run = await client.chat.start({
>     agentId: agent.id,
>     message: 'Use your Linear tools to list my Linear teams.',
> })
> const message = await run.result()
> console.log(message.status, '|', message.content)
> ```

> [tab] HTTP
>
> Send `POST /chat` with `options.agent_id` set to the agent's id. See the
> [API reference](https://docs.cominty.ai/api-reference.md).

An MCP server is mounted on the agent as a sub-agent. The message's tool calls
show a `subagent` call, not the integration's tool names. To turn MCP off for one
message, send a message scope that sets `mcp` to `enabled` false. See
[Keep some connections, or none](https://docs.cominty.ai/guides/capabilities-use-cases.md#recipe-3-keep-some-connections-or-none).

## Update an agent

An update is partial: send only what you want to change.

> [tab] Python SDK
>
> ```python theme={null}
> from cominty_sdk import AgentCapabilities, WebCapability
>
> agent = await client.agents.update(
>     agent.id, name="Linear helper v2", description=None
> )
> agent = await client.agents.update(
>     agent.id,
>     capabilities=AgentCapabilities(web=WebCapability(activation="always")),
> )
> print(agent.capabilities.model_dump())
> # {'web': {'activation': 'always'},
> #  'mcp': {'activation': 'always', 'connections': ['linear']},
> #  'memory': {'activation': 'never'}}
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> agent = await client.agents.update(agent.id, {
>     name: 'Linear helper v2',
>     description: null,
> })
> agent = await client.agents.update(agent.id, {
>     capabilities: { web: { activation: 'always' } },
> })
> console.log(agent.capabilities)
> // { web: { activation: 'always' },
> //   mcp: { activation: 'always', connections: ['linear'] },
> //   memory: { activation: 'never' } }
> ```

> [tab] HTTP
>
> ```bash theme={null}
> curl -X PUT "https://ds.cominty.com/agents/$AGENT_ID" \
>   -H "x-cominty-token: $COMINTY_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "name": "Linear helper v2",
>     "description": null,
>     "capabilities": {"web": {"activation": "always"}}
>   }'
> ```

* A null value (`None` in Python, `null` in JavaScript and HTTP) clears
  `description`, `instructions`, and `capabilities`.
* `capabilities` is **merged capability by capability**. Each capability you
  send replaces the stored one, and the others stay. In the example, `web`
  changed and `mcp` was kept.
* You cannot clear `name`, `scope`, or the override flag. The SDKs raise
  `InvalidParams` for a null value there, and for an update with no argument.
* An organization agent owned by someone else can be updated and deleted with the
  key.

## Choose the models

An agent has a model chain. The first model answers, and the next ones take over
when it fails.

> [tab] Python SDK
>
> ```python theme={null}
> models = await client.agents.list_models()
> agent = await client.agents.set_models(
>     agent.id, model_ids=[models[1].id, models[0].id]
> )
> print([model.name for model in agent.models])  # failover order
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> const models = await client.agents.listModels()
> agent = await client.agents.setModels(agent.id, {
>     modelIds: [models[1]!.id, models[0]!.id],
> })
> console.log(agent.models.map((model) => model.name)) // failover order
> ```

> [tab] HTTP
>
> ```bash theme={null}
> curl -X PUT "https://ds.cominty.com/agents/$AGENT_ID/models" \
>   -H "x-cominty-token: $COMINTY_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{"model_ids": ["MODEL_ID_1", "MODEL_ID_2"]}'
> ```

* An unknown id returns 404 with `detail` `Bad model_ids`. An empty list returns
  422\. The SDKs raise `InvalidParams` for an empty list, before any request.
* The model ids on `create` set the chain at creation. Omit them for the
  organization's default chain.

> [!WARNING]
>
> On a built-in agent, such as Chat or Hive, setting the model chain changes it
> for the whole organization. It affects every user. The built-in
> agents cannot be edited or deleted otherwise.

## Read and delete

> [tab] Python SDK
>
> ```python theme={null}
> summaries = await client.agents.list()   # AgentSummaryOut: no instructions, no models
> agent = await client.agents.get(agent.id)  # AgentOut: the full agent
> await client.agents.delete(agent.id)     # returns None
> ```

> [tab] JavaScript SDK
>
> ```ts theme={null}
> const summaries = await client.agents.list()   // AgentSummary: no instructions, no models
> agent = await client.agents.get(agent.id)      // AgentDetail: the full agent
> await client.agents.delete(agent.id)           // resolves to undefined
> ```

> [tab] HTTP
>
> ```bash theme={null}
> curl "https://ds.cominty.com/agents" -H "x-cominty-token: $COMINTY_API_KEY"
> curl "https://ds.cominty.com/agents/$AGENT_ID" -H "x-cominty-token: $COMINTY_API_KEY"
> curl -X DELETE "https://ds.cominty.com/agents/$AGENT_ID" -H "x-cominty-token: $COMINTY_API_KEY"
> ```
>
> `DELETE` answers 204 with no body.

`list` returns the built-in agents (`managed` is `true`), the organization
agents, and the key owner's private agents. A private agent of another member is
not there, and `get`, `update`, and `delete` on it return 404.

A delete is permanent. The messages the agent handled keep working, and report
their agent as `"ARCHIVED"`.

## Errors

| What happened | SDK | HTTP |
| - | - | - |
| Unknown agent, built-in agent on `update` or `delete`, another organization, or another member's private agent | `NotFoundError`, `detail` `Not Found` | 404 `Not Found` |
| Unknown model id | `NotFoundError`, `detail` `Bad model_ids` | 404 `Bad model_ids` |
| Empty `name`, `description` over 500 characters, `instructions` over 30000, empty model ids, or an `update` with nothing to change | `InvalidParams`, before any request | 422 |
| `skills.include` names a skill the key cannot read | `APIError` (422) | 422 |
| Delete twice | `NotFoundError` | 404 |

For the error classes, see the [Python SDK reference](https://docs.cominty.ai/sdk/reference.md#exceptions)
and the [JavaScript SDK reference](https://docs.cominty.ai/js-sdk/reference.md#errors).

## Next steps

> [card] [Skills](https://docs.cominty.ai/guides/skills.md)
>
> Upload a skill and give it to an agent.

> [card] [Sources](https://docs.cominty.ai/guides/sources.md)
>
> Index local files and let an agent search them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.