---
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; optional when API-triggered,
  defaults to the built-in `api_trigger` prompt
* [userPrompt](#npc-go-parameters-userPrompt): NPC user input; required 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

### Prompt Configuration {#npc-go-parameters-prompt}

[`role`](#npc-go-parameters-role), [`systemPrompt`](#npc-go-parameters-systemPrompt), and
[`userPrompt`](#npc-go-parameters-userPrompt) all relate to prompts. Whether you need to
configure them depends on how the build is triggered:

* **Comment-triggered** (`issue.comment@npc` / `pull_request.comment@npc`): the entry point
  is `@NPC` in a comment, and the platform starts the pipeline automatically and injects the
  prompts defined by the role in `.cnb/settings.yml`. **No configuration is needed**; the
  parameters above are ignored even if set (role definitions take higher priority).
* **API-triggered** ([`api_trigger`](../../trigger-rule.md#api_trigger), as well as
  `push` / `crontab` / manual triggers): you must **provide the prompts yourself** through
  `options`:
  * `systemPrompt` (**optional**): the system prompt; when omitted, the built-in
    `api_trigger` system prompt is used;
  * `userPrompt` (**required**): the user input; a missing or empty value is rejected;
  * `role` (optional): resolved from NPC roles in `.cnb/settings.yml` and appended to the
    system prompt as a personality block.

`npc.name=CodeBuddy` in the `api_trigger` request body only decides which agent identity the
build runs as (affecting pipeline display, title, billing category, CNB\_TOKEN permissions,
etc.); it does not provide prompts.

::: warning role alone cannot replace the prompts
`role` only appends the role prompt as a personality block; it provides neither the system
prompt nor the user input. `systemPrompt` may be omitted (the built-in `api_trigger` system
prompt is then used), but a missing or empty `userPrompt` is still rejected, as is configuring
only `role`:

```yaml title=".cnb.yml"
$:
  # A crontab trigger requires you to provide the prompts
  crontab:
    - cron: "0 10 * * *"
      docker:
        image: cnbcool/default-npc:latest
      stages:
        - name: npc go
          type: npc:go
          options:
            role: Release Guard
            # userPrompt still cannot be omitted; systemPrompt is optional and falls back to the built-in prompt
            systemPrompt: You are the release guard, responsible for checking and updating version numbers in the repository.
            userPrompt: Check and update the repository version numbers.
```

:::

### 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, defining the NPC's behavior guidelines and task boundaries.

Effective and **optional** 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.

When omitted, the built-in `api_trigger` system prompt is used (NPC baseline guidelines plus
tool-usage conventions), and Skills, knowledge bases, the
[`role`](#npc-go-parameters-role) personality block and project context are still appended.
This suits cases where the task is already fully described in
[`userPrompt`](#npc-go-parameters-userPrompt) and no extra behavior constraints are needed.

When [`role`](#npc-go-parameters-role) is configured you do not need to pass `systemPrompt`
either: the resolved role prompt is appended as a personality block on top of the built-in prompt.

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

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

NPC user input, mainly used for the user to describe tasks to the NPC.
**Required** for API-triggered builds (`api_trigger`); a missing or empty value is rejected.
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`.

Global-level Skills take priority over project-level Skills.
A global-level Skill with the same name will override its project-level counterpart,
so a stale copy checked into the repo cannot shadow the version shipped in the image.

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