---
url: /en/build/internal-steps/npc/go.md
---
`npc:go`

Executes an AI task in a specified Docker image.

When an NPC role is mentioned in an Issue or PR comment, the built-in system/user prompts are used. For other events,
you can customize the prompts via the `systemPrompt`, `userPrompt`, and `role` parameters.

You can install CLI tools and Skills required by the NPC at runtime in the image,
such as [CNB Skill](https://cnb.cool/cnb/skills/cnb-skill). For more NPC configuration, see [Custom NPC](../../npc.md).

* [Applicable Events](#npc-go-applicable-events)
* [Parameters](#npc-go-parameters)
* [Environment Variables](#npc-go-environment)
* [Timeout](#npc-go-timeout)
* [Output](#npc-go-output)
* [Configuration Examples](#npc-go-configuration-examples)

## Applicable Events {#npc-go-applicable-events}

[All Events](../../trigger-rule.md#trigger-event)

## Parameters {#npc-go-parameters}

### Parameters at a Glance

The list below enumerates all `npc:go` parameters by purpose, so you can get an overview
first and then jump to the relevant section for details.

* [role](#npc-go-parameters-role): NPC role name; only effective when API-triggered
* [systemPrompt](#npc-go-parameters-systemPrompt): NPC system prompt; only effective when API-triggered
* [userPrompt](#npc-go-parameters-userPrompt): NPC user input; only effective when API-triggered
* [model](#npc-go-parameters-model): Model ID used by the agent; effective in all events
* [maxTurns](#npc-go-parameters-maxTurns): Max agent conversation turns; effective in all events
* [contextWindow](#npc-go-parameters-contextWindow): Model context window size; effective in all events
* [maxTokens](#npc-go-parameters-maxTokens): Max output token count; effective in all events
* [thinkingLevel](#npc-go-parameters-thinkingLevel): Model reasoning depth; effective in all events
* [supportImage](#npc-go-parameters-supportImage): Whether to enable image input; effective in all events

`role`, `systemPrompt`, and `userPrompt` customize the NPC's prompts. Whether you need to
configure them depends on how the build is triggered:

* **Comment-triggered** (mentioning `@NPC` in an Issue/PR comment, i.e., the
  `issue.comment@npc` / `pull_request.comment@npc` events): the prompts are already
  provided by the NPC role, so **no configuration is needed**. The role and its prompts
  are defined in `.cnb/settings.yml` and take higher priority; `role`,
  `systemPrompt`, and `userPrompt` configured in this step are ignored.
* **API-triggered** ([`api_trigger`](../../trigger-rule.md#api_trigger)): you need to
  **configure the prompts yourself**. Setting `npc.name=CodeBuddy` in the request body
  only makes the build run with `@CodeBuddy` as the agent (affecting pipeline display, title,
  billing category, CNB\_TOKEN permissions, etc.); the prompts still need to be provided
  by you:
  * `systemPrompt` / `userPrompt`: pass them in this step's `options`;
  * `role` (optional): if configured, it is resolved from NPC roles in
    `.cnb/settings.yml` and appended to the system prompt.

### role {#npc-go-parameters-role}

* type: `String`
* required: `false`

NPC role name. It must be defined in the `roles` field of the NPC section in the `.cnb/settings.yml` file.
See [UI Customization](../../../repo/settings.md) for reference.
Takes effect only for API-triggered builds (`api_trigger`); ignored for comment-triggered builds
(`issue.comment@npc` / `pull_request.comment@npc`).

### systemPrompt {#npc-go-parameters-systemPrompt}

* type: `String`
* required: `false`

NPC system prompt.
Required only for API-triggered builds (`api_trigger`); ignored for comment-triggered builds
(`issue.comment@npc` / `pull_request.comment@npc`) since the prompts are provided by the NPC role.

### userPrompt {#npc-go-parameters-userPrompt}

* type: `String`
* required: `false`

NPC user input, mainly used for the user to describe tasks to the NPC.
Required only for API-triggered builds (`api_trigger`); ignored for comment-triggered builds
(`issue.comment@npc` / `pull_request.comment@npc`) since the prompts are provided by the NPC role.

### maxTurns {#npc-go-parameters-maxTurns}

* type: `Number`
* required: `false`

Maximum number of agent turns. Takes effect for all events.
When the limit is reached the agent is aborted, and the output may be incomplete.

When omitted, the value follows these rules:

* If no `model` is specified (platform default model is used), the `maxTurns` configured by the
  platform for the default model is used;
* If a custom `model` is specified, the platform-configured value is not used, and the value
  falls back to the built-in default `500`.

Explicitly passing a value always takes effect over the above.

### model {#npc-go-parameters-model}

* type: `String`
* required: `false`

Model id used by the agent. When omitted, the platform default model is used.
Takes effect for all events.

### contextWindow {#npc-go-parameters-contextWindow}

* type: `String | Number`
* required: `false`

Model context window size. Accepts:

* Lowercase-unit string: `"128k"` (k = 1000) or `"1m"` (m = 1000000)
* Plain number: `128000` or `"128000"`

Allowed range is `128k` ~ `1m` (i.e. 128000 ~ 1000000 tokens); out-of-range or malformed values
(uppercase, decimals, whitespace) are rejected. Used to trigger automatic summarization
compaction when context exceeds the limit; should match the actual context window of the selected
`model`. When omitted, the value follows these rules:

* If no `model` is specified (platform default model is used), the value configured by the platform
  CodeBuddy NPC for the default model is used;
* If a custom `model` is specified, the CodeBuddy NPC config is not inherited (context capacity
  varies by model and cannot be reused), and the value falls back to the built-in default `1m`
  (1000000).

Explicitly passing a value always takes effect over the above. Takes effect for all events.

Example:

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            contextWindow: 128k # equivalent to 128000, can also be written as "128000" or 128000

  # issue comment and PR comment events are configured identically; configure as needed
  pull_request.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            contextWindow: 128k # equivalent to 128000, can also be written as "128000" or 128000
```

### maxTokens {#npc-go-parameters-maxTokens}

* type: `String | Number`
* required: `false`

Model max output tokens. Accepts:

* Lowercase-unit string: `"48k"` (k = 1000) or `"1m"` (m = 1000000)
* Plain number: `64000` or `"64000"`

The accepted range is `200` ~ `1m` (i.e. 200 ~ 1000000 tokens); out-of-range or malformed values
(uppercase, decimals, whitespace) are rejected. Values in `[200, 48000)` are coerced up to
`48000` (48k) when the request is sent. When omitted, the value follows these rules:

* If no `model` is specified (platform default model is used), the value configured by the platform
  CodeBuddy NPC for the default model is used;
* If a custom `model` is specified, the CodeBuddy NPC config is not inherited (capabilities vary
  by model and cannot be reused), and the value falls back to the built-in default `48k` (48000).

Explicitly passing a value always takes effect over the above. Takes effect for all events.

Example:

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            maxTokens: 64k # equivalent to 64000, can also be written as "64000" or 64000

  # issue comment and PR comment events are configured identically; configure as needed
  pull_request.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            maxTokens: 64k # equivalent to 64000, can also be written as "64000" or 64000
```

### thinkingLevel {#npc-go-parameters-thinkingLevel}

* type: `String`
* required: `false`

Model reasoning depth (thinking level). Valid values: `off` / `minimal` / `low` / `medium` /
`high` / `xhigh` / `max`. When omitted, the value follows these rules:

* If no `model` is specified (platform default model is used), the value configured by the platform
  CodeBuddy NPC for the default model is used;
* If a custom `model` is specified, the CodeBuddy NPC config is not inherited (reasoning ability
  varies by model and cannot be reused), and the value falls back to the built-in default
  `medium`.

Explicitly passing a value always takes effect over the above. Takes effect for all events.

Example:

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            thinkingLevel: high # increase reasoning depth for deeper thinking; values include off / low / medium / high / xhigh / max

  # issue comment and PR comment events are configured identically; configure as needed
  pull_request.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            thinkingLevel: high # increase reasoning depth for deeper thinking; values include off / low / medium / high / xhigh / max
```

### supportImage {#npc-go-parameters-supportImage}

* type: `Boolean`
* required: `false`

Whether to enable the image input capability (multimodal). When enabled, the NPC can read and
understand images pasted into Issue / PR comment scenarios and the like (supported formats:
PNG / JPEG / WebP / GIF; a single image should not exceed 5 MiB).

When omitted, the value follows these rules:

* If no `model` is specified (platform default model is used), the switch configured by the
  platform CodeBuddy NPC for the default model is used;
* If a custom `model` is specified, the CodeBuddy NPC config is not inherited (image capability
  varies by model and cannot be reused), and the value falls back to the built-in default
  `false` (disabled).

Explicitly passing `true` registers the image-reading tool and declares image input; setting it
to `false` or leaving it unset keeps images treated as plain text.

Example:

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            supportImage: true # enable image input (multimodal)

  # issue comment and PR comment events are configured identically; configure as needed
  pull_request.comment@npc:
    default:
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            supportImage: true # enable image input (multimodal)
```

### Default Values of Model-Capability Parameters

[`model`](#npc-go-parameters-model), [`maxTurns`](#npc-go-parameters-maxTurns),
[`contextWindow`](#npc-go-parameters-contextWindow), [`maxTokens`](#npc-go-parameters-maxTokens),
[`thinkingLevel`](#npc-go-parameters-thinkingLevel), and [`supportImage`](#npc-go-parameters-supportImage)
are all tied to the **chosen model**: different models do not share the same capabilities
(context window, maximum output, reasoning depth, image input), so their defaults are not fixed.

No matter which parameter you configure, its value follows the same precedence rules:

1. If you **explicitly specify** the parameter, the value you pass wins.
2. If you do **not specify** it, the value depends on whether you specified `model`:
   * No `model` specified (using the platform default model): the platform's CodeBuddy NPC
     configuration for the default model is inherited.
   * A custom `model` is specified: the default model's configuration is not inherited, and
     the parameter falls back to the **built-in default** in the list below.

* [maxTurns](#npc-go-parameters-maxTurns): `500`
* [contextWindow](#npc-go-parameters-contextWindow): `1m` (1000000)
* [maxTokens](#npc-go-parameters-maxTokens): `48k` (48000)
* [thinkingLevel](#npc-go-parameters-thinkingLevel): `medium`
* [supportImage](#npc-go-parameters-supportImage): `false` (disabled)

> For each parameter, the exact value inherited from the default model when `model` is not
> specified is documented in that parameter's own section.

## Environment Variables {#npc-go-environment}

`npc:go` reads all environment variables of the current pipeline, including the platform's
built-in variables, the `env` and [`imports`](../../grammar.md#job-imports) at the pipeline /
stage / job levels, and [`exports`](../../grammar.md#job-exports) from upstream jobs.

## Timeout {#npc-go-timeout}

The [`timeout`](../../timeout.md#job-timeout) declared on the job applies to **each tool execution**
(e.g., bash commands) of the agent:
a single tool execution is forcibly interrupted and returns a failure to the agent once it exceeds the configured
duration or produces no output for that duration; if not declared, the default values apply
(10-minute no-output timeout, 2-hour maximum per execution).

The agent session itself has no overall timeout;
its total duration is bound by the [pipeline timeout](../../timeout.md#pipeline-timeout) (20 hours).

## Configuration Examples {#npc-go-configuration-examples}

**1. NPC event pipeline**: Invoke `npc:go` on the `issue.comment@npc` event.
The image must include the CLI tools and Skills required by the NPC runtime
(see step 2 below for building the image):

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    - docker:
        # Specify image containing CLI tools and Skills required by the NPC
        image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest
      stages:
        - name: npc go
          type: npc:go
```

**2. Build and push the NPC image**: Push the image to the artifact registry
so it can be used by the NPC event pipeline above:

```yaml title=".cnb.yml"
main:
  push:
    - services:
        - docker
      stages:
        - name: Docker build
          script: docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
        - name: Docker push
          script: docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
```

Install the Skills and CLI tools required by the NPC in the Dockerfile.
The following example installs `cnb-skill` and `cnb-cli`.

```Dockerfile title="Dockerfile"
FROM node:22-bookworm-slim

RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates git git-lfs curl jq ripgrep \
    && rm -rf /var/lib/apt/lists/* \
    && git lfs install \
    && npm install -g @cnbcool/cnb-cli skills \
    && npx skills add https://cnb.cool/cnb/skills/cnb-skill.git -g -y
```

Skills are automatically loaded from the following directories: `~/.agents/skills`,
`~/.codebuddy/skills` and their project-level counterparts: `.agents/skills`, `.codebuddy/skills`.

Project-level Skills take priority over user-level Skills.
A project-level Skill with the same name will override its user-level counterpart.

The NPC role prompt is defined in the `.cnb/settings.yml` file. See [Custom NPC](../../npc.md) for details.
