Tekton shared workspace
This example demonstrates the pattern from Shared volumes: a pipeline orchestrator manages a workspace PVC across steps, where a non-sandboxed step prepares the workspace, a sandboxed step runs an AI agent against it, and a final non-sandboxed step processes results — all sharing one PVC.
Key point: the sandboxed step is a separate pod
Unlike a normal Tekton step (a container in the Task's own pod), the
"sandboxed step" below doesn't run the agent directly. It runs the
openshell CLI, which calls the gateway to create a separate Sandbox
pod elsewhere in the sandbox namespace, waits for it to finish (via
--no-keep and a trailing command), and exits. Both pods — the Tekton
Task pod and the sandbox pod — need to mount the same PVC, which is
exactly the scenario the
RWO scheduling section of the
shared-volumes guide covers. Use ReadWriteMany storage for this PVC if
your cluster offers it.
Task
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: agent-shared-workspace
spec:
workspaces:
- name: shared-workspace
steps:
- name: prepare
image: alpine/git
script: |
#!/bin/sh
set -eu
git clone https://github.com/example/repo.git $(workspaces.shared-workspace.path)/repo
- name: run-agent-sandbox
# A custom image with the openshell CLI installed and the gateway's
# mTLS client cert already registered (see Authentication in
# docs/concepts/authentication.md) - baking this in avoids repeating
# `openshell gateway add` setup on every pipeline run.
image: quay.io/myorg/openshell-cli:latest
script: |
#!/bin/sh
set -eu
openshell sandbox create \
--gateway my-gateway \
--no-keep \
--driver-config-json '{
"kubernetes": {
"volumes": [
{"name": "shared", "persistent_volume_claim": {"claim_name": "'"$(context.taskRun.name)"'-shared-workspace"}}
],
"containers": {
"agent": {
"volume_mounts": [
{"name": "shared", "mount_path": "/workspace"}
]
}
}
}
}' \
-- sh -c 'cd /workspace/repo && claude "fix the failing tests"'
- name: push-results
image: alpine/git
script: |
#!/bin/sh
set -eu
cd $(workspaces.shared-workspace.path)/repo
git push origin HEAD:agent-fix-$(context.taskRun.name)
PipelineRun binding
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: agent-fix-run
spec:
taskRunTemplate:
serviceAccountName: ci-pipeline
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: agent-fix-run-shared-workspace
The PVC referenced here (agent-fix-run-shared-workspace) must:
- Already exist (or be created by a preceding
VolumeClaimTemplate/step) — it's an existing PVC from the sandbox's point of view, per Shared volumes - Live in the same namespace as
spec.sandbox.namespaceon theOpenShellGatewayCR, so the sandbox pod created inrun-agent-sandboxcan mount it - Use
ReadWriteManystorage if available, to avoid the RWO same-node-scheduling constraint between the Tekton pod and the sandbox pod
The ci-pipeline ServiceAccount is the same one granted workspace
membership in the
OpenShellWorkspaceMember sample —
see Shared volumes
for the two supported non-interactive auth paths.