# Cordium Agent

> Cordium documentation. Canonical page: <https://octelium.com/docs/cordium/latest/use/agent>.

The Cordium Agent is an AI agent that is built into the Cordium web portal at `https://cordium.<DOMAIN>/agent`. You chat with it, and it manages your *Workspaces* for you: it creates, starts, stops and deletes them, runs commands and test suites inside them, copies files between them, reads their logs, uses the Octelium *Services* you are authorized to access, and can use everything else exposed by the Cordium API. Here are some examples of what you can ask it:

- "Run the payments-api test suite against the `feat/ledger-v2` branch on Go 1.25 and Go 1.26 in parallel and tell me what fails."
- "Snapshot `k3x9`, then upgrade all the Go dependencies in it and run the tests. Roll back if anything breaks."
- "Which of my *Workspaces* have been stopped for more than a week? Delete the ephemeral ones."
- "Query the `pg-staging` database for the 10 slowest endpoints of the last hour and chart them."

## How It Works

Unlike hosted AI assistants, the Cordium Agent runs inside your own *Cluster*, inside your own *Workspace*, with your own identity:

```text
Cordium web portal (chat UI)
   │  HTTP/JSON + SSE (https://<WORKSPACE>.cordium.<DOMAIN>, authenticated as you)
   ▼
cordium-agent (a process inside your agent Workspace)
   ├─ Workspace tools: create, control, exec, copy files and read logs of your Workspaces
   ├─ Cordium API tools: search, describe and call any Cordium API method
   ├─ Presentation tools: tables, charts, resource cards and downloadable artifacts
   ├─ Built-in tools: read, write, edit, grep, find, ls and bash (the agent's own Workspace is its computer)
   └─ LLM: your Claude or ChatGPT subscription, or an Octelium LLM Service
```

- **Your own *Workspace*.** The first time you open the agent page, the portal provisions your personal agent: a system `USER` *Space* named `octelium.<USER>`, a `cordium-agent` *Template* inside it, and a *Workspace* that runs the [`@octelium/cordium-agent`](https://www.npmjs.com/package/@octelium/cordium-agent) npm package and serves it as its default application. The portal starts that *Workspace* whenever you open the agent page.
- **Your own identity.** The agent calls the Cordium API through the *Workspace*'s authentication proxy, exactly like the `cordium` CLI does inside any *Workspace*. Every call is authorized server-side for you, and the model never sees a credential. It can only do what you can do, and Octelium *Policies* apply to it like to any other *Workspace* (read more [here](https://octelium.com/docs/cordium/latest/management/access-control.md)).
- **Commands in other *Workspaces*.** Commands in your other *Workspaces* are executed through the Cordium API (i.e. the same mechanism as `cordium exec`), so no SSH is needed. Tool calls of the same turn run concurrently, so the same operation can run in several *Workspaces* at once. The agent refuses to stop, restart or delete its own *Workspace*.
- **Persistence.** Conversations, files you upload, artifacts the agent produces and your settings are stored in the agent's *Workspace*. Restarting the agent resumes your conversations with their full context.

## Models

You can sign in with your own Claude (Pro or Max) or ChatGPT subscription directly from the agent page. The OAuth flows run inside your agent *Workspace* and the tokens never leave it. Alternatively, your *Cluster* administrators can configure a default model served by an Octelium LLM *Service* (read more [below](#configuring-the-agent)), in which case the agent works out of the box without any API key while every inference request is authorized and audited by Octelium. You can switch the model and the thinking level at any time from the chat.

## Approvals

Every Cordium API method that the agent can call is classified by risk: `read`, `write`, `destructive` (e.g. deletions), and `sensitive` (e.g. *Secrets*, *Memberships* and shared ports). Depending on the approval mode, the agent pauses and asks for your approval in the chat before executing a call:

| Mode          | The agent asks for approval before                    |
| ------------- | ----------------------------------------------------- |
| `never`       | Nothing.                                              |
| `destructive` | Destructive and sensitive calls. This is the default. |
| `write`       | Every call that is not read-only.                     |

You can additionally require approvals for every shell command, whether in the agent's own *Workspace* or in your other *Workspaces*. Both settings can be changed at any time from the chat.

> **Note:**
>
> Approvals are a user-experience safety net, not the security boundary. Authorization is always enforced by the *Cluster*: the agent can never exceed your own permissions, and you can further restrict what your *Workspace* *Sessions* are allowed to do via Octelium *Policies* (read more [here](https://octelium.com/docs/cordium/latest/management/access-control.md#policies-for-workspace-sessions)).

## Skills

The agent loads [Agent Skills](https://github.com/octelium/octelium-skills) at startup, including the `cordium` skill, which teaches it how to write *Workspace* and *Template* configurations and how to manage the underlying Octelium resources. Your administrators can add more skills repositories or local skill directories via the agent configuration.

## Configuring the Agent

The agent is configured Cluster-wide by the administrators via the `agent` section of the [ClusterConfig](https://octelium.com/docs/cordium/latest/management/clusterconfig.md#agent). The following `agent` section sets a default model that is served by an Octelium LLM *Service* named `claude` and sets the compute resources of the agent *Workspaces*:

```yaml
kind: ClusterConfig
spec:
  agent:
    llm:
      service: claude
      model: claude-opus-5-5
    limit:
      cpu:
        millicores: 2000
      memory:
        megabytes: 4096
    config:
      llm:
        api: anthropic-messages
      approvals:
        api: write
```

> **Note:**
>
> `cordium man apply` replaces the entire `ClusterConfig` spec. Always start from your current configuration via `cordium man get cc -o yaml`, add the `agent` section to it and apply the result (read more [here](https://octelium.com/docs/cordium/latest/management/clusterconfig.md)).

And here is the corresponding Octelium LLM *Service* (read more about LLM *Services* [here](https://octelium.com/docs/octelium/latest/management/core/service/llm/overview.md)):

```yaml
kind: Service
metadata:
  name: claude
spec:
  mode: LLM
  config:
    upstream:
      url: https://api.anthropic.com
    llm:
      protocol: ANTHROPIC
      auth:
        custom:
          header: x-api-key
          value:
            fromSecret: anthropic-api-key
```

> **Note:**
>
> Your *Users* must be authorized by an Octelium *Policy* to access the LLM *Service*. Since every inference request goes through Octelium, you can also apply per-*User* token rate limits, guardrails and model restrictions via the LLM *Service* plugins (read more [here](https://octelium.com/docs/octelium/latest/management/core/service/llm/plugins.md)).

The `agent` section supports the following fields:

| Field                      | Description                                                                                                                                  |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `isDisabled`               | Disables the agent for all the *Users*. Already existing agent *Workspaces* are not deleted.                                                 |
| `llm.service`, `llm.model` | The default Octelium LLM *Service* (`NAME` or `NAME.NAMESPACE`) and model. If unset, *Users* can still sign in with their own subscriptions. |
| `version`                  | The version or npm dist-tag of the `@octelium/cordium-agent` package. Defaults to the version that matches the *Cluster*.                    |
| `image`                    | The container image of the agent *Workspaces*. Node.js 22.19 or later is installed automatically on the first start if the image lacks it.   |
| `limit`                    | The compute resources of the agent *Workspaces*.                                                                                             |
| `config`                   | Any additional agent configuration, merged on top of the generated one (see below).                                                          |

Here are the most useful fields of the agent's own configuration that can be set via `config`:

| Field                      | Default                         | Description                                                                                                  |
| -------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `llm.api`                  | `openai-completions`            | The API spoken by the LLM endpoint, e.g. `openai-responses`, `anthropic-messages` or `google-generative-ai`. |
| `llm.thinkingLevel`        | `medium`                        | The default thinking level, from `off` to `max`.                                                             |
| `llm.loginProviders`       | `["anthropic", "openai"]`       | The subscriptions the *Users* can sign in with. Set it to `[]` to only allow the Octelium LLM *Service*.     |
| `approvals.api`            | `destructive`                   | The default approval mode: `never`, `destructive` or `write`.                                                |
| `approvals.commands`       | `false`                         | Requires an approval for every shell command.                                                                |
| `agent.systemPromptAppend` |                                 | Extra instructions appended to the system prompt (e.g. your organization's conventions).                     |
| `agent.maxConcurrentRuns`  | `4`                             | The maximum number of concurrent runs across conversations.                                                  |
| `skills.repositories`      | `octelium/octelium-skills@main` | The Agent Skills repositories cloned at startup.                                                             |
| `webSearch`                |                                 | Enables web search via `brave`, `tavily` or `searxng`.                                                       |

## Running the Agent in Your Own Workspaces

The agent is an ordinary npm package, which means that it can also run in any other *Workspace* whose image has Node.js 22.19 or later and `git`. This is useful to give a team its own agent with its own configuration and *Template*. Here is an example:

```yaml
spec:
  image:
    registry:
      url: node:24-bookworm
  runtime:
    envVars:
      - key: CORDIUM_AGENT_CONFIG_JSON
        value: '{"llm":{"provider":"octelium","service":"claude","api":"anthropic-messages","model":"claude-opus-5-5"},"approvals":{"api":"write"}}'
    tasks:
      - name: cordium-agent
        type: POST_START
        isBackground: true
        run: npx --yes --prefer-online @octelium/cordium-agent@latest serve
  applications:
    - name: agent
      displayName: Cordium Agent
      port: 8080
      isDefault: true
```

You can check the configuration, the Cordium API access and the LLM access from inside the *Workspace* as follows:

```bash
npx @octelium/cordium-agent doctor
```

> **Note:**
>
> Do not share the agent's application with other *Users*: the agent acts with the identity of the *Workspace*'s owner.

## HTTP API

The agent exposes an HTTP/JSON and Server-Sent Events API under `/v1` at its *Workspace*'s hostname, which is what the web portal uses. You can use it to build your own clients. Here are the main endpoints:

| Method         | Path                                   | Description                                                                                         |
| -------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `GET`          | `/v1/info`                             | The agent's version, model, identity, settings and capabilities.                                    |
| `GET`, `POST`  | `/v1/conversations`                    | List the conversations, or create one and optionally start a run: `{"title"?, "input"?: {"text"}}`. |
| `GET`          | `/v1/conversations/{id}`               | A conversation, its messages and the snapshot of its active run.                                    |
| `POST`         | `/v1/conversations/{id}/runs`          | Start a run: `{"input": {"text"}}`.                                                                 |
| `GET`          | `/v1/runs/{id}/events`                 | The run's events as an SSE stream. It can be resumed via `Last-Event-ID`.                           |
| `POST`         | `/v1/runs/{id}/cancel`                 | Cancel a run.                                                                                       |
| `POST`         | `/v1/runs/{id}/approvals/{approvalId}` | Approve or reject a pending call: `{"decision": "approve" \| "reject"}`.                            |
| `GET`, `PUT`   | `/v1/models`, `/v1/model`              | List the models or switch the current one.                                                          |
| `GET`, `PATCH` | `/v1/settings`                         | Read or update the approval settings.                                                               |
