> For the complete documentation index, see [llms.txt](https://ai-docs.fptcloud.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ai-docs.fptcloud.com/fpt-ai-inference/fpt-ai-inference/code-agents-with-token-factory.md).

# Code Agents with Token Factory

This explains how to connect popular code agents to Token Factory through the FPT AI Marketplace.\
Use it to configure endpoints, API keys, an internal proxy, and the right model for each tool. See **`Task recommendation by roles`** to select an LLM for each task.

### Use code agents effectively

Give AI models clear instructions to prevent endless agent loops and incorrect implementation paths. This prevents endless agent loops and incorrect implementation paths.

**Instruction principles — use English where possible:**

* **Use `AGENTS.md`** — place it at the repository root. Agents read its context, working principles, and common commands at session start. OpenCode, Cline, and Roocode support this automatically. This instruction includes an `AGENTS.md` file.
  * `AGENTS.md` → for **OpenCode (Sisyphus)**
  * `CLAUDE.md` → for **Claude CLI** (`claude`)
* **Keep prompts short, specific, and example-driven** — instead of *"fix the auth"*, write: *"In `auth.py:45`, replace `token = req.headers.get('token')` with `token = req.headers.get('Authorization', '').removeprefix('Bearer ')`"*
* **Control code loops** — when an agent repeats work without progress, use: *"Stop. Summarize what you've tried and what's blocking you."* You can also add a stopping condition: *"If you can't fix it in 3 attempts, stop and explain."*
* **Break tasks into smaller steps** — *"Only do step 1: write the function. Don't run or test yet."* Always ask the agent to **plan first, then execute**: *"List the steps you'll take. Don't execute yet."*

***

**API Endpoint:** `https://mkp-api.fptcloud.com/v1`\
**Company proxy:** `http://10.36.232.10:8080`

***

### 1. OpenCode

#### Installation

```powershell
# Request administrator access at: https://uservice.fci.vn/secure/SSC01CreateTicket.jspa?processId=147&catalogId=2&issueKeys=
# Select the Whitelist option.

# Install Node.js LTS.
winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements

# Install OpenCode with npm, Scoop, or Chocolatey.
npm install -g opencode-ai
# Or run: scoop install opencode  /  choco install opencode
```

#### API configuration

File: `%USERPROFILE%\.config\opencode\opencode.jsonc`

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "fpt": {
      "name": "fpt",
      "npm": "@ai-sdk/openai-compatible",
      "models": {
        "Qwen3.6-27B": { "name": "Qwen3.6-27B" }
      },
      "options": {
        "baseURL": "https://mkp-api.fptcloud.com/v1",
        "headers": {
          "Authorization": "Bearer <API_KEY>"
        }
      }
    }
  }
}
```

#### Run on Windows

```powershell
$env:HTTPS_PROXY = "http://10.36.232.10:8080"
$env:HTTP_PROXY  = "http://10.36.232.10:8080"
$env:NO_PROXY    = "localhost,127.0.0.1"

opencode
```

***

#### Ubuntu

**Installation:**

```bash
# Request administrator access at: https://uservice.fci.vn/secure/SSC01CreateTicket.jspa?processId=147&catalogId=2&issueKeys=
# Select the Whitelist option.

# Install Node.js LTS, required by OpenCode.
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install OpenCode with the official installer.
export https_proxy="http://10.36.232.10:8080"
export http_proxy="http://10.36.232.10:8080"
export no_proxy="localhost,127.0.0.1"

curl -fsSL https://opencode.ai/install | bash
```

Or use npm:

```bash
npm install -g opencode-ai
```

**API configuration:**

Create the OpenCode directory if needed: `mkdir $HOME/.config/opencode`

Create `opencode.jsonc`: `touch $HOME/.config/opencode/opencode.jsonc`

Create an API key for `Qwen 3.6-27B` in the AI Marketplace: `https://marketplace.fptcloud.com/`

Update `$HOME/.config/opencode/opencode.jsonc`:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "fpt": {
      "name": "fpt",
      "npm": "@ai-sdk/openai-compatible",
      "models": {
        "Qwen3.6-27B": { "name": "Qwen3.6-27B" }
      },
      "options": {
        "baseURL": "https://mkp-api.fptcloud.com/v1",
        "headers": {
          "Authorization": "Bearer <API_KEY>"
        }
      }
    }
  }
}
```

**Run:**

```bash
export HTTPS_PROXY="http://10.36.232.10:8080"
export HTTP_PROXY="http://10.36.232.10:8080"
export NO_PROXY="localhost,127.0.0.1"

opencode
```

***

#### Optional

For an improved experience, install the [oh-my-openagent plugin](https://github.com/code-yeongyu/oh-my-openagent).

### 2. Cline (VS Code extension)

1. Install the **Cline** extension in VS Code.
2. Open Cline **Settings** → select **API Provider: OpenAI Compatible**.
3. Enter:

| Field    | Value                             |
| -------- | --------------------------------- |
| Base URL | `https://mkp-api.fptcloud.com/v1` |
| API Key  | `<API_KEY>`                       |
| Model    | `Qwen3.6-27B`                     |

4. Configure the proxy in VS Code settings (`settings.json`):

```json
"http.proxy": "http://10.36.232.10:8080"
```

***

### 3. Roocode (VS Code extension)

See the [OpenAI-compatible provider connection guide](https://docs.roocode.com/providers/openai-compatible).

Enter:

* **Base URL:** `https://mkp-api.fptcloud.com/v1`
* **API Key:** `<API_KEY>`
* **Model:** `Qwen3.6-27B`

***

### 4. Claude CLI with FPT AI Marketplace

Claude CLI sends API keys in the Anthropic-style `x-api-key` header. FPT AI Marketplace requires `Authorization: Bearer`. The following configuration overrides environment variables for marketplace compatibility. It also uses a separate configuration directory to avoid conflicts with a claude.ai account.

> **Note:** The following configuration uses the MODAS Vietnam site only

{% hint style="info" %}
Currently, use the fixed stable Claude Code version ***2.1.150**.* Disable automatic updates in `settings.json`:

`{`\
`"theme": "dark",`\
`"model": "opus",`\
`"env": {`\
`"DISABLE_AUTOUPDATER": "1"`\
`}`\
`}`
{% endhint %}

#### Configuration — add to your PowerShell profile

Open your profile:

```powershell
notepad $PROFILE
```

Add this to the end of the file:

```powershell
$env:MKP_API_BASE = "https://mkp-api.fptcloud.com"
$env:MKP_API_KEY  = "sk-..."

function claude-mkp {
    $model = if ($env:CLAUDE_MKP_MODEL) { $env:CLAUDE_MKP_MODEL } else { "Qwen3.6-27B" }

    $savedApiKey = $env:ANTHROPIC_API_KEY
    $savedOAuth  = $env:CLAUDE_CODE_OAUTH_TOKEN
    Remove-Item Env:ANTHROPIC_API_KEY        -ErrorAction SilentlyContinue
    Remove-Item Env:CLAUDE_CODE_OAUTH_TOKEN  -ErrorAction SilentlyContinue

    $env:CLAUDE_CONFIG_DIR              = "$env:USERPROFILE\.claude-mkp"
    $env:ANTHROPIC_BASE_URL             = $env:MKP_API_BASE
    $env:ANTHROPIC_AUTH_TOKEN           = $env:MKP_API_KEY
    $env:ANTHROPIC_MODEL                = $model
    $env:ANTHROPIC_SMALL_FAST_MODEL     = $model
    $env:ANTHROPIC_DEFAULT_SONNET_MODEL = $model
    $env:ANTHROPIC_DEFAULT_OPUS_MODEL   = $model
    $env:ANTHROPIC_DEFAULT_HAIKU_MODEL  = $model
    $env:HTTPS_PROXY                    = "http://10.36.232.10:8080"
    $env:HTTP_PROXY                     = "http://10.36.232.10:8080"
    $env:NO_PROXY                       = "localhost,127.0.0.1"

    try {
        claude @args
    } finally {
        if ($savedApiKey) { $env:ANTHROPIC_API_KEY = $savedApiKey }
        else { Remove-Item Env:ANTHROPIC_API_KEY -ErrorAction SilentlyContinue }
        if ($savedOAuth)  { $env:CLAUDE_CODE_OAUTH_TOKEN = $savedOAuth }
        else { Remove-Item Env:CLAUDE_CODE_OAUTH_TOKEN -ErrorAction SilentlyContinue }
        @("CLAUDE_CONFIG_DIR","ANTHROPIC_BASE_URL","ANTHROPIC_AUTH_TOKEN",
          "ANTHROPIC_MODEL","ANTHROPIC_SMALL_FAST_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL",
          "ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL",
          "HTTPS_PROXY","HTTP_PROXY","NO_PROXY") | ForEach-Object {
            Remove-Item "Env:$_" -ErrorAction SilentlyContinue
        }
    }
}

function ccdm { claude-mkp --dangerously-skip-permissions @args }
```

#### Commands

| Command             | Description                                |
| ------------------- | ------------------------------------------ |
| `claude-mkp`        | Runs Claude CLI through MKP                |
| `claude-mkp <args>` | Passes additional arguments as usual       |
| `ccdm`              | Runs with `--dangerously-skip-permissions` |

Temporarily change the model:

```powershell
$env:CLAUDE_MKP_MODEL = "other-model"; claude-mkp
```

***

#### Ubuntu

Add this to `~/.bashrc` or `~/.zshrc`:

```bash
export MKP_API_BASE="https://mkp-api.fptcloud.com"
export MKP_API_KEY="sk-..."

claude-mkp() {
    local model="${CLAUDE_MKP_MODEL:-Qwen3.6-27B}"

    local saved_api_key="$ANTHROPIC_API_KEY"
    local saved_oauth="$CLAUDE_CODE_OAUTH_TOKEN"
    unset ANTHROPIC_API_KEY
    unset CLAUDE_CODE_OAUTH_TOKEN

    export CLAUDE_CONFIG_DIR="$HOME/.claude-mkp"
    export ANTHROPIC_BASE_URL="$MKP_API_BASE"
    export ANTHROPIC_AUTH_TOKEN="$MKP_API_KEY"
    export ANTHROPIC_MODEL="$model"
    export ANTHROPIC_SMALL_FAST_MODEL="$model"
    export ANTHROPIC_DEFAULT_SONNET_MODEL="$model"
    export ANTHROPIC_DEFAULT_OPUS_MODEL="$model"
    export ANTHROPIC_DEFAULT_HAIKU_MODEL="$model"
    export HTTPS_PROXY="http://10.36.232.10:8080"
    export HTTP_PROXY="http://10.36.232.10:8080"
    export NO_PROXY="localhost,127.0.0.1"

    claude "$@"
    local exit_code=$?

    if [ -n "$saved_api_key" ]; then
        export ANTHROPIC_API_KEY="$saved_api_key"
    else
        unset ANTHROPIC_API_KEY
    fi
    if [ -n "$saved_oauth" ]; then
        export CLAUDE_CODE_OAUTH_TOKEN="$saved_oauth"
    else
        unset CLAUDE_CODE_OAUTH_TOKEN
    fi
    unset CLAUDE_CONFIG_DIR ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN \
          ANTHROPIC_MODEL ANTHROPIC_SMALL_FAST_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL \
          ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL \
          HTTPS_PROXY HTTP_PROXY NO_PROXY

    return $exit_code
}

ccdm() { claude-mkp --dangerously-skip-permissions "$@"; }
```

Temporarily change the model:

```bash
CLAUDE_MKP_MODEL="other-model" claude-mkp
```

#### Why use `ANTHROPIC_AUTH_TOKEN` instead of `ANTHROPIC_API_KEY`?

| Sent header                    | Variable               | Accepted by MKP? |
| ------------------------------ | ---------------------- | ---------------- |
| `x-api-key: sk-...`            | `ANTHROPIC_API_KEY`    | No → 401         |
| `Authorization: Bearer sk-...` | `ANTHROPIC_AUTH_TOKEN` | Yes → 200 OK     |

#### Test the connection

```powershell
curl.exe -sS -X POST "$env:MKP_API_BASE/v1/messages" `
  -H "Authorization: Bearer $env:MKP_API_KEY" `
  -H "anthropic-version: 2023-06-01" `
  -H "Content-Type: application/json" `
  -d '{"model":"Qwen3.6-27B","max_tokens":20,"messages":[{"role":"user","content":"hi"}]}'
```

#### Troubleshooting

| Symptom                         | Cause and resolution                                                              |
| ------------------------------- | --------------------------------------------------------------------------------- |
| Auth conflict warning           | Ensure `CLAUDE_CONFIG_DIR` is set inside the function, not globally.              |
| `Retrying in Xs · attempt N/10` | MKP rejected authentication. Use `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY`. |
| 401 "Missing API Key"           | The header is incorrect. Use `Authorization: Bearer`, not `x-api-key`.            |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://ai-docs.fptcloud.com/fpt-ai-inference/fpt-ai-inference/code-agents-with-token-factory.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
