> For the complete documentation index, see [llms.txt](https://docs.apolo.us/index/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apolo.us/index/apolo-mcp/guides/full-mode-service-account.md).

# Full mode with a service account

`APOLO_MCP_POLICY_MODE=full` removes Apolo MCP's ownership restriction and allows the agent to mutate any supported resource that its Apolo identity may access. **Never run full mode using a personal owner, administrator, or otherwise broadly privileged Apolo account.** A prompt mistake, malicious repository content, compromised dependency, or shell command could then exercise all of that account's permissions, including outside the intended experiment.

For unattended or headless use, create a dedicated service account, grant its role only the permissions required for one use case, store its one-time token in an Apolo secret, and run the agent inside a bounded R\&D job. The MCP policy remains useful as an operational guardrail, while the service account's RBAC becomes the actual security boundary.

Use the [Apolo R\&D Session Setup skill](/index/apolo-mcp/capabilities/skills/apolo-rnd-session-setup.md) from the trusted local `managed` session to plan and provision this workflow. Use the [Apolo R\&D Session Operations skill](/index/apolo-mcp/capabilities/skills/apolo-rnd-session-operate.md) inside the resulting job to verify isolation, configure Codex or Claude Code, optionally start `tmux`, and hand monitoring instructions back to the operator.

## 1. Design the least-privilege grant set

Resolve one exact cluster, organization, and project before creating anything. Answer these questions for the specific experiment:

| Question                                                      | Safe default                                                                                               |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Which exact resource URIs must the agent inspect?             | Grant `read` only on those resources or narrow prefixes.                                                   |
| Which resources must it create, change, or delete?            | Grant `write` only on the narrowest applicable parent URI. Apolo `write` includes deletion.                |
| Must it change sharing or RBAC?                               | No. Do not grant `manage`; Apolo MCP does not expose ACL administration.                                   |
| Must it launch nested jobs or Flow runs?                      | Grant workload access only in the experiment project and enforce job lifetime and quota limits separately. |
| Must it handle storage, images, disks, buckets, or secrets?   | Grant each resource family independently; do not grant a whole project merely for convenience.             |
| Does it need the bootstrap-token secret after the job starts? | No additional MCP grant is normally needed. The trusted launcher mounts that secret into the job.          |

Use complete Apolo resource URIs. The service account has its own role, returned as `account.role` when it is created. Grant resources directly to that role:

```console
apolo acl grant <RESOURCE_URI> <SERVICE_ACCOUNT_ROLE> read
apolo acl grant <WRITABLE_RESOURCE_URI> <SERVICE_ACCOUNT_ROLE> write
apolo acl ls -u <SERVICE_ACCOUNT_ROLE> --full-uri
```

Review the final `apolo acl ls` output before launching the agent. Prefer several exact grants over one broad grant. Use `manage` only when the use case genuinely requires the service account to delegate permissions; ordinary full-mode MCP operation does not.

## 2. Create the account without exposing its token

Perform this setup in a trusted interactive session, not in the headless agent being provisioned. Start Apolo MCP in `managed` mode and call [`create_service_account`](/index/apolo-mcp/capabilities/tools/service-accounts.md#create_service_account) with values equivalent to:

```json
{
  "destination_type": "secret",
  "destination_name": "mcp-full-mode-config",
  "name": "mcp-full-mode-agent",
  "cluster": "<CLUSTER>",
  "org": "<ORG>",
  "project": "<PROJECT>"
}
```

The tool writes the complete one-time service-account token directly to the named Apolo secret and returns only safe account metadata, including `account.role`. The complete token embeds the API URL and default context and is accepted by Apolo SDK as `APOLO_PASSED_CONFIG`. It must never be pasted into a prompt, shell command, log, source file, or MCP configuration.

Grant the reviewed resource set to the returned role using the trusted operator's `apolo acl grant` commands. ACL administration intentionally remains outside the MCP tool surface, so the agent cannot grant itself more access through Apolo MCP.

## 3. Prepare the agent runtime and configure MCP

The following self-contained runtime and job configuration is also packaged with the `apolo-rnd-session-operate` skill used inside the job.

### Runtime requirements inside an R\&D job

Use `node:22-bookworm-slim` as an example bootstrap image and record that exact mutable tag. Apolo job launch does not currently accept Docker image digest references. This is an upstream convenience image, not an Apolo-supported R\&D image; another glibc-based Debian or Ubuntu image is acceptable when it provides Node.js 22 and Python 3.11 or newer.

Start the bounded job with `sleep infinity`, enter it with `apolo exec`, and install the runtime there. Before running package-manager or network commands, show the resolved versions and complete command plan and obtain confirmation. On the suggested image, install the common system dependencies as the job's privileged user:

```console
apt-get update
apt-get install --yes --no-install-recommends \
  ca-certificates \
  curl \
  git \
  pipx \
  python3 \
  python3-venv
```

Install the Apolo client bundle and packaged skills into the job user's environment. Replace every version and client placeholder with a resolved value; install only the selected coding client or clients.

```console
export PATH="$HOME/.local/bin:$PATH"
pipx install apolo-all==<APOLO_ALL_VERSION>
npm config set prefix "$HOME/.local"
npm install --global @openai/codex@<CODEX_VERSION>
npm install --global @anthropic-ai/claude-code@<CLAUDE_CODE_VERSION>
```

Do not run both npm commands unless both clients were requested. Never silently substitute `latest` or execute an uninspected remote installer through a pipe. Git, language runtimes, build tools, and similar utilities beyond the common bootstrap are workload dependencies; add only those required by the target repository.

After installing the selected client, use an ephemeral agent configuration directory and run the unified setup. Set `CODEX_HOME` only when Codex was selected:

```console
export CODEX_HOME=/tmp/codex-home
apolo-mcp setup <codex|claude|both> --policy-mode full
```

The command registers the job-local MCP server, forwards the complete Apolo environment contract, and links the packaged skills. Do not point the agent configuration or authentication home into `/workspace`.

`tmux` is optional. Install it only when an interactive client needs detach/reattach support:

```console
apt-get install --yes --no-install-recommends tmux
```

`tmux` does not keep the session alive after the Apolo job terminates.

Verify the selected client and the two Apolo entry points before continuing. Take the Apolo MCP package version from `pipx list`; the current CLI does not expose a version flag.

```console
node --version
python3 --version
pipx list
apolo --version
apolo-mcp --version
# Run one or both, matching the installation:
codex --version
claude --version
```

### Isolated R\&D job configuration

For unattended `full` operation, the job must expose a dedicated service account's complete token as `APOLO_PASSED_CONFIG`, use a clean `APOLO_CONFIG`, and set `APOLO_MCP_POLICY_MODE=full`. Never use `--pass-config` or mount the launching user's `~/.apolo`.

Mount an approved Apolo storage path read-write at `/workspace` and make it the job's working directory. Keep repositories, generated outputs, non-secret diagnostics, and a sanitized `/workspace/HANDOFF.md` there so a replacement job can mount the same path and continue. The handoff should record the current goal, completed work, verification results, pending work, and artifact paths. Keep Apolo and coding-provider credentials, agent authentication stores, terminal transcripts, and environment dumps outside the persistent mount.

Forward those job variables to Apolo MCP in job-local Codex configuration:

```toml
[mcp_servers.apolo]
command = "apolo-mcp"
env_vars = [
  "APOLO_CONFIG",
  "APOLO_MCP_POLICY_MODE",
  "APOLO_PASSED_CONFIG",
]
```

For Claude Code, use job-local configuration:

```json
{
  "mcpServers": {
    "apolo": {
      "command": "apolo-mcp",
      "args": [],
      "env": {
        "APOLO_CONFIG": "${APOLO_CONFIG}",
        "APOLO_MCP_POLICY_MODE": "full",
        "APOLO_PASSED_CONFIG": "${APOLO_PASSED_CONFIG}"
      }
    }
  }
}
```

Keep this configuration inside the isolated image or job workspace. Never make `full` the user's global desktop default.

## 4. Launch a bounded R\&D job

Select `node:22-bookworm-slim`, or another reviewed slim glibc-based image meeting the requirements above. Supply coding-agent provider credentials separately according to that provider's headless-operation guidance. Launch the bootstrap job with explicit context, a bounded lifetime, a clean Apolo configuration directory, and the service-account secret:

```console
apolo run \
  --cluster <CLUSTER> \
  --org <ORG> \
  --project <PROJECT> \
  --preset <PRESET> \
  --name mcp-full-mode-agent \
  --life-span 8h \
  --detach \
  --volume storage:<RND_WORKSPACE_PATH>:/workspace:rw \
  --workdir /workspace \
  --env APOLO_CONFIG=/tmp/apolo-agent-config \
  --env APOLO_MCP_POLICY_MODE=full \
  --env APOLO_PASSED_CONFIG=secret:mcp-full-mode-config \
  node:22-bookworm-slim -- sleep infinity
```

This image reference is an example, not an Apolo-supported R\&D runtime. After the job starts, enter it with `apolo exec <JOB_ID> -- bash`, follow the runtime bootstrap above, and then start the selected coding client.

Create or select the storage path before launch and reuse it for replacement jobs. Keep source, outputs, and a sanitized `/workspace/HANDOFF.md` there. Do not store the service-account configuration, coding-provider credentials, agent authentication state, terminal transcripts, or environment dumps in that persistent workspace.

Do **not** use `--pass-config`: that would pass the launching user's current Apolo credentials into the job and defeat the service-account isolation. Do not mount the launcher's `~/.apolo` directory. Verify from inside the job that Apolo reports the service-account identity and expected context before starting autonomous work.

The token is available to processes inside the job, including the agent, because that is required for authentication. It is therefore not protected from the agent itself; the protection comes from the token belonging to a narrowly permissioned service account. Restrict outbound network access where practical, avoid printing environment variables, and terminate the job when the experiment completes.

## 5. Audit and clean up

After the run:

1. Inspect the service account's grants and the resources changed during the run.
2. Remove or revoke grants that are no longer needed.
3. Delete the R\&D job and experiment resources according to the project's retention policy.
4. Delete the bootstrap secret and service account when the identity is no longer required. Treat persistent service accounts as long-lived credentials that need ownership, review, and rotation procedures.

The local Apolo MCP lifecycle journal can help explain cooperating MCP actions, but it is not a tamper-proof security or compliance audit log. Use Apolo-side audit facilities and organizational controls when authoritative records are required.
