Make behavior-based overrides
If configuration overrides aren’t enough, for example, you need to skip a step, add new logic, or replace how something works, then it’s time to use a behavior override.
Behavior overrides let you change how a scope runs by customizing its workflows. You can:
- Skip or replace workflow steps
- Add new scripts or logic
- Inject behavior based on conditions (like platform type or scope kind)
This is especially useful when you're building advanced scopes (like background workers or scheduled tasks) and need full control over runtime behavior.
How it works
Each scope defines its lifecycle as a set of ordered YAML steps (e.g., create, initial, delete). These
workflows live in the base scope repo.
You can override those steps by placing your own workflow files in the same path inside your override repo. When the agent detects these files, it uses them instead of the default ones.
You can:
action: skip– ignore specific stepsaction: replace– fully replace a step with a custom script- Insert your own named steps using
type: script,type: command, etc.
Note: See the lifecycle execution flow for scope actions for more details.
Repo structure
Place workflow overrides under scope/workflows/ or deployment/workflows/ depending on the lifecycle action you're
customizing.
your-override-repo/
├── scope/ # Scope lifecycle actions
│ └── my_domain_generator
│ └── workflows/
│ ├── create.yaml
│ ├── update.yaml
│ └── ..
├── deployment/
│ └── build_tolerations
│ └── workflows/
│ ├── initial.yaml
│ ├── blue_green.yaml
├── values.yaml # Your configuration overrides
└── ..
After changing your override repo, you’ll need to refresh the agent sources so it pulls the latest code.
Example 1: Skip DNS configuration
By default, the create lifecycle step includes logic to generate a DNS record. If you're building something that
doesn’t need networking, like a background worker, you can skip this step.
Create a create.yaml in your overrides repo:
your-override-repo/
├── scope/ # Scope lifecycle actions
│ └── workflows/
│ ├── create.yaml
And add a step like this:
steps:
- name: networking
action: skip
When this override is active, the networking step won't run during scope creation.
Example 2: Add tolerations for arm64 deployments
Say you want your application to run only on arm64 nodes. Kubernetes uses tolerations for this. You can inject them dynamically using a script override.
What you’ll do:
- Create a script that checks the asset's platform (e.g.
arm_64) - Add tolerations to the deployment context if needed
- Insert that script into the deployment workflows (
initial.yaml,blue_green.yaml)
File structure
These are the files you'll need to create throughout the guide.
your-override-repo/
├── deployment/
│ └── build_tolerations # your shell script
│ └── workflows/
│ ├── initial.yaml
│ ├── blue_green.yaml
└── ..
-
In your
build_tolerationsscript:#!/bin/bash
# Find the platform of the asset being deployed
ASSET_PLATFORM=$(echo "$CONTEXT" | jq -r .asset.platform)
MODIFIERS=$(echo "$CONTEXT" | jq .k8s_modifiers)
# ARM64 assets require a toleration to target the correct Kubernetes node
if [[ "$ASSET_PLATFORM" == "arm_64" ]]; then
TOLERATIONS='[{"key": "architecture", "operator": "Equal", "value": "arm64", "effect": "NoSchedule"}]'
echo "The asset is built for arm, adding tolerations to the deployment"
echo "$TOLERATIONS" | jq .
# Add the toleration to the modifiers and
# store it in the context so it is included in the deployment manifest
MODIFIERS=$(echo "$MODIFIERS" | jq --argjson tolerations "$TOLERATIONS" '
if .deployment then
.deployment.tolerations = (.deployment.tolerations // []) + $tolerations
else
.deployment = {"tolerations": $tolerations}
end
')
CONTEXT=$(echo "$CONTEXT" | jq --argjson modifiers "$MODIFIERS" '.k8s_modifiers = $modifiers')
fiThis script modifies the deployment context only if the target architecture is arm64.
-
Then, add the step in
initial.yaml:steps:
- name: build_tolerations
type: script
file: "$OVERRIDES_PATH/deployment/build_tolerations"
after: build context -
Repeat the same step in
blue_green.yamlif you're using both strategies.
$OVERRIDES_PATH points to the root of your override repo inside the agent. It’s set in your notification channel
configuration as the --override-path.
Example path: /root/.np/your-org/your-repo
In both workflows, we've added a build_tolerations step that runs your custom script right after the build context
step, allowing the scope to inject tolerations dynamically during deployment.
Example 3: Generate your own domain
Scopes automatically generate a domain name during the create step. If you want to control the format of that domain, you can override just the step that generates it.
File structure
your-override-repo/