Key points
- The controls are independent.
agent_roleis persona and behaviour,knowledge_contextis what the model is told,mcp_profilesis which tools it may call, andgovernance_leveldecides how hard a guardrail bites. - Pipeline, step, and task MCP profiles are additive and deduplicated, not overriding, and pipeline YAML cannot declare arbitrary MCP server URLs.
governance_levelacceptsadvisoryorstrictand defaults tostrict; a task falls back to the step, then the pipeline.- Knowledge context is merged across pipeline, step, and task rather than replaced, and
guardrailandpolicyentries also validate direct scripts before execution. agent_rolecannot be set on a task: parsing fails withtask "<name>" cannot define agent_role; set agent_role on the pipeline or step.llm_content_preloadis a prompt-size and cost control, not a permission. Usellm_content_includeandllm_content_ignoreto shape what the retrieval tools can reach.- Every referenced profile must exist, be enabled, and be allowed in the run scope.
Examples
agent_role: senior-release-engineer
governance_level: strict
mcp_profiles:
- jira-readonly
knowledge_context:
- kind: guardrail
ref: security/repo-check
required: true
llm_content_preload: false
llm_content_include:
- "src/**/*.go"
llm_content_ignore:
- "**/testdata/**"name: release-service
description: Build, verify, and publish the payments service.
container_image: alpine:3.20
working_directory: /workspace
timeout: 45m
display_option: list
llm_enabled: true
model: reasoning-large
agent_role: senior-release-engineer
governance_level: strict
mcp_profiles:
- jira-readonly
knowledge_context:
- kind: guardrail
ref: security/repo-check
required: true
llm_content_preload: false
llm_content_include:
- "src/**/*.go"
llm_content_ignore:
- "**/testdata/**"
variables:
- RELEASE_CHANNEL
- platform/shared:ARTIFACT_BUCKET
steps:
- name: build
script: |
make build
echo "1.0.$(date +%s)" > /nopsai/outputs/BUILD_TAG
outputs:
- name: BUILD_TAG
- name: verify
image: golang:1.24
depends_on: [build]
runtime_pool: ci
volumes:
- build-cache:/root/.cache
script: |
go vet ./...
go test ./...
- name: checks
depends_on: [verify]
tasks:
- name: licenses
ignore_failure: true
script: |
./scripts/license-check.sh
- name: sbom
script: |
./scripts/sbom.sh > /workspace/sbom.json
sha256sum /workspace/sbom.json | cut -d' ' -f1 > /nopsai/outputs/SBOM_DIGEST
outputs:
- name: SBOM_DIGEST
- name: risk-review
depends_on: [checks.sbom]
goal: Review the changed files and list the risks this release carries.
model: reasoning-large
governance_level: advisory
mcp_profiles:
- jira-readonly
knowledge_context:
- kind: example
path: .nopsai/docs/risk-review-example.md
- name: report
depends_on: [checks.licenses, checks.sbom]
variables:
SBOM_DIGEST: $steps.checks.sbom.outputs.SBOM_DIGEST
script: |
echo "checks complete"
echo "sbom $SBOM_DIGEST"
- name: package
depends_on: [checks]
secrets:
- REGISTRY_TOKEN
- platform/shared:SIGNING_KEY
variables:
BUILD_TAG: $steps.build.outputs.BUILD_TAG
script: |
./scripts/package.sh "$BUILD_TAG"
echo "channel $RELEASE_CHANNEL, bucket $ARTIFACT_BUCKET"
./scripts/mint-token.sh > /nopsai/outputs/PUBLISH_TOKEN
./scripts/sign.sh --key "$SIGNING_KEY" --token "$REGISTRY_TOKEN"
outputs:
- name: PUBLISH_TOKEN
sensitive: true
- name: announce
depends_on: [package]
condition: Only run when the release channel is stable.
ignore_failure: true
script: |
./scripts/announce.sh
- name: production-gate
depends_on: [package]
approval:
type: production-release
teams:
- platform/sre
allow_self_approval: false
timeout: 24h
- name: publish
depends_on: [production-gate]
script: |
./scripts/promote.sh
- name: release-notes
depends_on: [publish]
goal: Read the commits since the last tag and write release notes to /workspace/NOTES.md.
model: reasoning-large
agent_role: release-writer
governance_level: advisory
mcp_profiles:
- github-readonly
knowledge_context:
- kind: policy
ref: platform/release-notes
required: true - name: risk-review
goal: Review the changed files.
agent_role: reviewerField reference
agent_rolepipelinestringOptionalConfigured default agent role
Default AI persona and instruction profile for conditions and goals.
agent_role: senior-release-engineerAny enabled Agent role ID
- Referenced profile must exist and be enabled.
- Tasks cannot set
agent_role; parsing fails with an explicit error.
steps[].agent_role
pkg/models/model.go
mcp_profilespipelinestring[]OptionalNone
Approved MCP tool profiles available to LLM goal work anywhere in the pipeline.
mcp_profiles:
- jira-readonly- Each profile must be configured, enabled, and allowed in the run scope.
- Pipeline, step, and task profiles are additive and deduplicated, not overriding.
- Pipeline YAML cannot declare arbitrary MCP server URLs.
The agent only accepts server/tool pairs present in the resolved profile allowlist.
services/nopsai/pkg/validation/pipeline.go
governance_levelpipelinestringOptionalstrict
How NopsAI enforces the AI policy review decision. An unset value normalizes to strict.
governance_level: advisoryadvisory, strict
steps[].governance_level, tasks[].governance_level
Lowering this from the default weakens fail-closed enforcement for the whole run.
pkg/models/policy_merge.go
knowledge_contextpipelineknowledge_ref[]OptionalNone
Knowledge documents merged into every effective LLM task context. guardrail and policy entries also validate direct scripts before execution.
knowledge_context:
- kind: guardrail
ref: security/repo-check
required: true- Merged with step and task knowledge context rather than replaced by it.
services/nopsai/pkg/validation/pipeline.go
llm_content_preloadpipelinebooleanOptionalfalse
Whether workspace file listings and contents are loaded into the prompt up front. This is a prompt-size and cost control, not a permission: with it false the model receives no unrequested file dump, but bounded workspace tools can still retrieve files on demand.
llm_content_preload: trueNot a confidentiality boundary. Use llm_content_ignore or llm_content_include to keep a file out of the model’s reach, since those shape the workspace index the retrieval tools read from. Shared and retrieved files carry path, SHA-256, size, and workspace revision metadata so stale file replacements are rejected.
pkg/models/model.go
llm_content_includepipelinestring[]OptionalNone
Include filters applied to files shared with LLM goal context.
llm_content_include:
- "src/**/*.go"llm_content_ignorepipelinestring[]OptionalNone
Ignore filters applied to files shared with LLM goal context. Applied after include filters.
llm_content_ignore:
- "**/testdata/**"steps[].agent_rolestepstringOptionalPipeline `agent_role`
Persona override for the step condition and any LLM goals in the step.
agent_role: security-reviewer- Referenced profile must exist and be enabled.
- Not valid at task level.
steps[].mcp_profilesstepstring[]OptionalNone
MCP profiles added for LLM goals in this step. Additive with pipeline and task profiles.
mcp_profiles:
- github-readonly- Invalid on
includesteps. - Invalid on
scriptsteps. - Each profile must be configured, enabled, and allowed in the run scope.
services/nopsai/pkg/validation/pipeline.go
steps[].governance_levelstepstringOptionalPipeline `governance_level`, otherwise strict
AI governance enforcement override for this step.
governance_level: strictadvisory, strict
tasks[].governance_level
steps[].knowledge_contextstepknowledge_ref[]OptionalNone
Knowledge references merged with pipeline and task context for this step.
knowledge_context:
- kind: policy
ref: platform/deploy-policytasks[].agent_roletasknot supportedOptionalNone
Not valid on tasks. Parsing fails with task "<name>" cannot define agent_role; set agent_role on the pipeline or step.
# set agent_role on the pipeline or step instead- Rejected during YAML and JSON unmarshaling, not only at validation time.
pkg/models/model.go
tasks[].mcp_profilestaskstring[]OptionalNone
MCP profiles for this LLM goal task. Additive with pipeline and step profiles.
mcp_profiles:
- jira-readonly- Invalid on script tasks.
services/nopsai/pkg/validation/pipeline.go
tasks[].governance_leveltaskstringOptionalStep, then pipeline, otherwise strict
Most specific AI governance enforcement override.
governance_level: advisoryadvisory, strict
tasks[].knowledge_contexttaskknowledge_ref[]OptionalNone
Most specific knowledge references for this task, merged with step and pipeline context.
knowledge_context:
- kind: example
path: .nopsai/docs/migration-example.mdHow it works
Read these directives as four questions with four answers. Conflating them is the usual source of surprise: raising the governance level does not change which tools are available, and adding a knowledge document does not change who the agent is acting as.
Because MCP profiles are additive, a step cannot narrow what the pipeline already granted. Narrowing is a configuration decision made where the profile is defined, not in the manifest.
llm_content_preload: false means the model receives no unrequested file dump, but bounded workspace tools can still retrieve files on demand. Files that must stay out of reach belong in llm_content_ignore, because that shapes the index the retrieval tools read from.
Shared and retrieved files carry path, SHA-256, size, and workspace revision metadata, so a file replaced mid-run is rejected rather than silently used.
Implementation evidence
pkg/models/model.goPipeline, step, and task field definitions.
doc/knowledge-context.mdKnowledge document kinds, merging, and runtime snapshots.
doc/mcp-pipeline-integration.mdProfile resolution and tool-call boundaries.

