kubernetes: One run. One pod. Nothing shared.

On Kubernetes, every isolated ConvOps run is its own Job: a fresh pod with its own volume and secret, locked down, time limited, and gone when the work is done.

one job per run · per-run secret · no service-account token · pod security restricted

namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h
job stream · example
2pods live119records kept0shared
  • run-d51eBump dependenciessucceeded
  • run-2a9fRelease notes v4.2running
  • run-7f3aFix refund roundingjob created
in short

How do you run AI agents on Kubernetes safely?

One Kubernetes Job per run: a fresh pod with its own volume and Secret, no service-account token, Pod Security restricted, isolated by NetworkPolicy and deleted when the run ends.

ConvOps is the operations layer for AI agents: an MCP server that holds your team's process as workflows, with approval gates, a shared memory and an audit trail. It runs no AI models.

key facts · october 2026

  • Run pods are created without a service-account token, run as non-root with every Linux capability dropped, under the Pod Security restricted profile.
  • A NetworkPolicy allows no ingress and limits egress to what the run needs. MCP servers can run as sidecars in the same pod.
  • Each run gets its own Kubernetes Secret, mounted for that run only, and the values are masked in logs.
  • Enterprise customers self-host the whole system on their own Kubernetes with one Helm chart.
  • At Neomanex, 3 of the 17 configured executors start each dispatch as its own Kubernetes Job with its own volume and Secret (October 2026).

best for

  • Platform teams that want agent runs isolated from each other and from the cluster API.
  • Enterprises that need runs, secrets and models to stay inside their own cluster.

not for

  • Teams without Kubernetes who only work attended in their AI client. They do not need this layer.

updated

the problem

One shared box runs every agent.

Agents on a shared server or a laptop share its disk, its keys and its fate. Nobody owns the blast radius.

“Whose files are these?”

Every agent run shares one box. One run's half-finished branch and stray files leak into the next.

“Who has the keys?”

Tokens live on laptops and shared servers, readable by every job that runs there.

“Can anyone stop it?”

A runaway agent keeps going until someone notices, finds the box and kills the process.

“Where did the work go?”

The box restarts and two hours of unpushed work vanish with it.

watch it run

One run, from Job to record.

An example task, Fix refund rounding, routed to an isolated executor. Follow the pod from creation to deletion.

01ConvOps

One task, one Job.

A step is routed to an isolated executor. ConvOps creates a Kubernetes Job for this run, mounts the task volume and a secret made for this run only.

namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h
run-7f3a · events · example
›job/run-7f3a created · namespace convops-runs
02volume task-8c1e mounted · kept across steps
03secret run-7f3a mounted · GITHUB_TOKEN=••••••••masked
02the pod

Sidecars first, then the agent.

The MCP servers the environment names start as sidecars inside the pod. Once they answer, the agent starts in the main container.

namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h
run-7f3a · events · example
›job/run-7f3a created · namespace convops-runs
02volume task-8c1e mounted · kept across steps
03secret run-7f3a mounted · GITHUB_TOKEN=••••••••masked
04sidecar github-mcp ready
05sidecar browser-mcp ready
06agent started · claude-code
03the cluster

Locked down before it works.

No service-account token. Non-root, every capability dropped, Pod Security restricted. No ingress, limited egress. Then the agent gets to work.

namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h
run-7f3a · events · example
›job/run-7f3a created · namespace convops-runs
02volume task-8c1e mounted · kept across steps
03secret run-7f3a mounted · GITHUB_TOKEN=••••••••masked
04sidecar github-mcp ready
05sidecar browser-mcp ready
06agent started · claude-code
07posture: no sa token · non-root · caps dropped
08network policy: no ingress · egress limited
04the agent

The work is pushed.

A clean fast-forward to the branch you named, or a task branch for review. Commits carry the identity you set on the environment.

main
Fast-forwardClean history: the work lands on main.
run-7f3a · events · example
›job/run-7f3a created · namespace convops-runs
02volume task-8c1e mounted · kept across steps
03secret run-7f3a mounted · GITHUB_TOKEN=••••••••masked
04sidecar github-mcp ready
05sidecar browser-mcp ready
06agent started · claude-code
07posture: no sa token · non-root · caps dropped
08network policy: no ingress · egress limited
09edit src/billing/refund.ts · 48 tests passed
10pushed convops/task/8c1e
›
05ConvOps

A failure keeps the work.

If the run fails, nothing is thrown away. The commits go to a rescue branch, and the task volume is still there to resume.

main
RescueThe run failed. The commits are kept on convops/rescue/8c1e.
06the record

The pod goes. The record stays.

The pod is deleted. What remains is the run record: tokens, model split, cost, turns, duration, and the error class if it failed.

pod run-7f3adeletedtask volumekept
runFix refund rounding · examplescheduled
queuedpod startingworkingpushing
pushed
tokens0k
turns0
cost$0.00
duration0m 0s
namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h
run-7f3a · events · example
›job/run-7f3a created · namespace convops-runs
02volume task-8c1e mounted · kept across steps
03secret run-7f3a mounted · GITHUB_TOKEN=••••••••masked
what's inside

Everything the run needs. Nothing else.

One pod per run. Each part is there for a reason, and each one is gone when the run ends, except the work.

namespaceconvops-runs
podrun-7f3apending
main
agentclaude-code
pushed
sidecar
github-mcpMCP sidecar
sidecar
browser-mcpMCP sidecar
task volumeworking copy, kept across stepskept
run secretthis run only
scratchgone with the pod
run-7f3asucceededpushedrun record kept
  • no service-account token
  • non-root
  • capabilities dropped
  • pod security restricted
  • network policy
  • time limit 4h

run pod · example

  • Task volume

    The working copy. Kept across the task's steps, so the next step and any resume pick up where this one stopped.

  • Run secret

    A Kubernetes Secret made for this run. Values are masked in every log and transcript.

  • MCP sidecars

    MCP servers start as native sidecars before the agent, with per-tool allow and deny.

  • No cluster credentials

    No service-account token is mounted. The agent cannot talk to the Kubernetes API.

  • Least privilege

    Non-root, every capability dropped, under the Pod Security restricted profile.

  • Network policy

    No ingress at all. Egress limited to what the run needs.

  • Time limit

    Set per executor, 4 hours by default. The run cannot outlive it.

where the work goes

Pushed, or kept. Never lost.

A clean fast-forward when history allows. A task branch when it does not. A rescue branch when the run fails.

main
Fast-forwardThe history is clean: the work moves the ref forward. No merge commit.
time limits and stop

You can always pull the plug.

Every executor has a time limit, 4 hours by default. Stop works on any run. A run that hits its limit resumes where it was.

runMigrate pricing table · examplescheduled
queuedpod startingworkingpushing
stopped
tokens0k
cost$0.00
duration0m 0s

You saw it heading the wrong way and pressed Stop. The pod ends and the run is recorded as stopped.

runWeekly SEO audit · examplescheduled
queuedpod startingworkingresumedpushing
pushed
tokens0k
cost$0.00
duration0m 0s

The run hit its time limit. It resumed on the same task volume and finished without starting over.

self-host

Your cluster. One Helm chart.

Enterprise runs the whole system on its own Kubernetes. Runs, environments, secrets and records stay inside your cluster.

ConvOps cloud7 of 8
Workflow engine
Brain
Audit
Web app
Isolated runs
Environments
Secrets
MCP over HTTPSoutbound only
Your Kubernetes1 of 8
Your models

ConvOps cloud We run everything. Your AI clients and models stay yours and connect over MCP.

one command · example

Install it like any other chart.

your terminal · examplehelm
your clusterempty
namespace convops
API and workflow engine
Web app
Workers
Run namespace
Your model keys
namespace convops-runs · one pod per run
run-7f3arun-91c2run-4be0
nothing has to leave
  • Your cluster

    ConvOps runs in your Kubernetes from one Helm chart. Runs are Jobs in a namespace you own.

  • Your models and credentials

    Bring your own model provider and keys. Git access, secrets and MCP servers stay yours.

  • Nothing has to leave

    Code, secrets, transcripts and run records stay inside your cluster.

the ideas

Four ideas hold it together.

Isolation

One Job per run. A fresh pod with no cluster credentials, no ingress and nothing from the run before.

one run, one pod

The task volume

The working copy lives on a per-task volume. It outlasts the pod, so steps continue and runs resume.

kept across steps

Sidecars

MCP servers run beside the agent in the same pod, started first, with per-tool allow and deny.

native sidecars

Rescue

A failed run never loses its work. The commits are pushed to a rescue branch you can pick up.

failure keeps the work

the difference

A shared server vs a pod per run.

  • Every run shares one disk. Yesterday's files leak into today's work.
  • Keys sit on the box, readable by every job that runs there.
  • The agent can reach the cluster API and anything on the network.
  • A runaway job runs until someone notices and logs in.
  • The box dies and the half-finished work dies with it.
  • Nobody can say what ran, for how long, or at what cost.

The run pod

One Job per run. No service-account token, non-root, capabilities dropped, a deadline from the executor time limit, MCP servers as native sidecars (init containers with restartPolicy Always).

payload
# run pod spec (example, trimmed)
apiVersion: batch/v1
kind: Job
metadata:
  name: run-7f3a
  namespace: convops-runs
spec:
  backoffLimit: 0
  activeDeadlineSeconds: 14400   # executor time limit
  template:
    spec:
      automountServiceAccountToken: false
      restartPolicy: Never
      securityContext:
        runAsNonRoot: true
        seccompProfile: { type: RuntimeDefault }
      initContainers:
        - name: github-mcp           # native sidecar
          image: example/github-mcp
          restartPolicy: Always
          securityContext:
            allowPrivilegeEscalation: false
            capabilities: { drop: ["ALL"] }
      containers:
        - name: agent
          image: example/agent-claude-code
          securityContext:
            allowPrivilegeEscalation: false
            capabilities: { drop: ["ALL"] }
          envFrom:
            - secretRef: { name: run-7f3a }
          volumeMounts:
            - { name: task, mountPath: /work }
      volumes:
        - name: task
          persistentVolumeClaim:
            claimName: task-8c1e
Job spec, trimmed. Example values.

One values file

Self-hosted installs set the run namespace, posture, network policy, time limit and model credentials in one Helm values file.

payload
# values.yaml (example)
runs:
  namespace: convops-runs
  podSecurity: restricted
  networkPolicy:
    ingress: none
    egress: limited
  timeLimit: 4h
  taskVolume:
    size: 10Gi
models:
  existingSecret: model-credentials
Helm values. Example keys.

No ingress, limited egress

Every pod in the run namespace is selected by a policy that admits nothing in and lets only the egress the run needs out.

payload
# run namespace network policy (example)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: runs-isolation
  namespace: convops-runs
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]
  ingress: []          # no ingress at all
  egress:
    - ports:
        - { port: 443, protocol: TCP }
NetworkPolicy. Example.

The record that stays

When the pod is gone, the run record remains: tokens, per-model split, cost, turns, duration and the error class.

payload
{
  "task": "Fix refund rounding",
  "executor": "isolated-sonnet",
  "status": "succeeded",
  "pushed": "convops/task/8c1e",
  "tokens": { "input": 151200, "output": 30800 },
  "models": { "sonnet": 0.91, "haiku": 0.09 },
  "cost_usd": 1.94,
  "turns": 34,
  "duration_s": 700,
  "outcome": "succeeded"
}
Run record. Example values.
questions

What security reviewers ask.

Can a run reach the Kubernetes API?

No. Run pods are created without a service-account token, so the agent has no credentials for the cluster API. The pod runs as non-root, with every Linux capability dropped, under the Pod Security restricted profile.

What can a run talk to on the network?

A NetworkPolicy isolates every run pod: no ingress at all, and egress limited to what the run needs. MCP servers it uses can run as sidecars inside the same pod, so those calls never leave it.

Where do secrets live, and who can see them?

Secrets are stored once through a one-time link, never pasted in chat. Each run gets its own Kubernetes Secret, mounted for that run only, and the values are masked in every log and transcript.

What happens if a run hangs or goes wrong?

Every executor has a time limit (4 hours by default) and Stop works on any run. A run that hits its limit can resume on the same volume. A failed run keeps its work on a rescue branch.

Is anything left behind after a run?

The pod is deleted when the run ends. The task volume stays so the next step continues from the same working copy. The run record stays too: tokens, model split, cost, turns, duration and any error class.

Can we run this on our own cluster?

Yes. Enterprise customers self-host ConvOps on their own Kubernetes with one Helm chart. Runs, environments and secrets stay in your cluster, with your own models and credentials. Nothing has to leave.

Which agents run in the pod?

Claude Code and OpenCode today. The design is agent-neutral, so Codex, Kimi and others plug in the same way: an engine in the main container, your environment around it.