Agent Runtimes
Agent runtimes let Orka delegate task execution to external agent CLIs—such as Codex CLI, Claude Code CLI, and GitHub Copilot CLI—instead of running tasks through Orka's built-in AI worker. This gives your tasks access to full autonomous coding capabilities (file read/write/edit, bash execution, git operations) provided by battle-tested agent runtimes, while Orka handles scheduling, lifecycle management, secrets, sessions, and Kubernetes-native orchestration.
Supported Runtimes
| Runtime | runtime.type | Secret Key | Status |
|---|---|---|---|
| Codex CLI | codex | OPENAI_API_KEY or CODEX_API_KEY | GA |
| Claude Code CLI | claude | ANTHROPIC_API_KEY (direct) or ANTHROPIC_FOUNDRY_API_KEY (Azure AI Foundry) | GA |
| GitHub Copilot CLI | copilot | GITHUB_TOKEN | Technical Preview |
Live Coverage
PR-blocking live CI currently exercises these runtime scenarios against real model families:
codex+ GPT with a pinned git workspace andpriorTaskRefclaude+ Claude withsessionRefcopilot+ Gemini with a pinned public repo checkout
This coverage is about Orka's runtime wiring and task/session/workspace behavior. The live backend used in CI is harness infrastructure, not the main product under test.
Quick Start
1. Create a Secret
# For Codex CLI
kubectl create secret generic codex-api-key \
--from-literal=OPENAI_API_KEY=sk-proj-...
# For Claude Code CLI
kubectl create secret generic claude-api-key \
--from-literal=ANTHROPIC_API_KEY=sk-ant-...
# For GitHub Copilot CLI
kubectl create secret generic copilot-token \
--from-literal=GITHUB_TOKEN=ghp_...
Azure AI Foundry
Claude Code CLI supports Azure AI Foundry as an alternative to direct Anthropic API access. To use Azure AI Foundry, include the Foundry-specific environment variables in the secret:
kubectl create secret generic claude-credentials \
--from-literal=CLAUDE_CODE_USE_FOUNDRY=1 \
--from-literal=ANTHROPIC_FOUNDRY_API_KEY=your-key \
--from-literal=ANTHROPIC_FOUNDRY_RESOURCE=your-resource-name \
--from-literal=ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-4-5
| Variable | Required | Description |
|---|---|---|
CLAUDE_CODE_USE_FOUNDRY | Yes | Set to 1 to enable Azure AI Foundry |
ANTHROPIC_FOUNDRY_API_KEY | Yes | Azure AI Foundry API key |
ANTHROPIC_FOUNDRY_RESOURCE | Yes | Azure AI Foundry resource name |
ANTHROPIC_DEFAULT_SONNET_MODEL | Yes | Deployment name (e.g. claude-sonnet-4-5) |
ANTHROPIC_DEFAULT_HAIKU_MODEL | No | Optional Haiku deployment name |
ANTHROPIC_DEFAULT_OPUS_MODEL | No | Optional Opus deployment name |
All secret keys are injected as environment variables into the worker pod via envFrom, so any Claude Code CLI environment variable can be passed through the secret.
2. Create an Agent
apiVersion: core.orka.ai/v1alpha1
kind: Agent
metadata:
name: claude-agent
spec:
model:
name: "claude-sonnet-4-20250514"
systemPrompt:
inline: "You are a helpful coding assistant."
secretRef:
name: claude-api-key
execution:
runtimeClassName: gvisor
nodeSelector:
sandbox-runtime: gvisor
runtime:
type: claude
defaultMaxTurns: 50
defaultAllowBash: true
defaultAllowedTools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
3. Create a Task
apiVersion: core.orka.ai/v1alpha1
kind: Task
metadata:
name: refactor-task
spec:
type: agent
agentRef:
name: claude-agent
prompt: "Refactor the main.go file to use structured logging"
timeout: "30m"
4. Get the Result
kubectl get task refactor-task
# Get the result via the REST API
curl http://localhost:8080/api/v1/tasks/refactor-task/result \
-H "Authorization: Bearer $(kubectl create token orka-client)"
Agent Configuration
An Agent resource with a runtime field defines the CLI runtime to use for type: agent tasks. The runtime field is mutually exclusive with providerRef (which is for type: ai tasks).
Full Reference
apiVersion: core.orka.ai/v1alpha1
kind: Agent
metadata:
name: my-agent
spec:
# runtime marks this Agent for type: agent tasks
runtime:
# type: which CLI runtime to use (required)
# Valid values: "copilot", "claude", "codex"
type: claude
# defaultMaxTurns: default max agent loop iterations per task
# Range: 1-1000, Default: 50
defaultMaxTurns: 50
# defaultAllowedTools: tools available by default
# Claude tools: Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch
defaultAllowedTools:
- Read
- Glob
- Grep
# defaultAllowBash: allow bash commands by default
# Default: true
defaultAllowBash: true
# secretRef: Secret containing API credentials
# Codex runtime expects: OPENAI_API_KEY or CODEX_API_KEY
# Claude runtime expects: ANTHROPIC_API_KEY
# Copilot runtime expects: GITHUB_TOKEN
secretRef:
name: claude-api-key
# execution: default runtime and placement settings for worker pods
execution:
runtimeClassName: gvisor
nodeSelector:
sandbox-runtime: gvisor
tolerations:
- key: sandbox-runtime
operator: Equal
value: gvisor
effect: NoSchedule
# systemPrompt: injected via --system-prompt flag
systemPrompt:
inline: "You are a coding assistant."
# Or reference a ConfigMap:
# configMapRef:
# name: my-prompt-configmap
# key: prompt.txt
# model: LLM model configuration (passed as --model flag)
model:
name: "claude-sonnet-4-20250514"
# resources: compute resources for worker pods
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
Task Configuration
Tasks with type: agent reference an Agent and can override its runtime defaults.
Full Reference
apiVersion: core.orka.ai/v1alpha1
kind: Task
metadata:
name: my-agent-task
spec:
# type: must be "agent" for CLI runtime tasks
type: agent
# agentRef: references an Agent with runtime configured (required)
agentRef:
name: claude-agent
# namespace: defaults to task namespace
# namespace: other-ns
# execution: task-level runtime/placement overrides
execution:
runtimeClassName: kata-qemu
nodeSelector:
sandbox-runtime: kata
# prompt: instruction sent to the agent CLI
prompt: "Fix the failing tests in api/"
# agentRuntime: task-level overrides (all optional)
agentRuntime:
# workspace: git clone configuration
workspace:
gitRepo: "https://github.com/example/my-project.git"
branch: "main"
# ref: specific commit SHA or tag (mutually exclusive with branch)
# ref: "abc123"
# gitSecretRef: Secret with git credentials for private repos
# gitSecretRef:
# name: git-credentials
# subPath: subdirectory within repo to use as workspace root
# subPath: "services/api"
# forkRepo: writable fork URL used as git remote for pushes
# forkRepo: "https://github.com/my-org/my-project.git"
# prBaseBranch: upstream branch to target when creating PRs
# prBaseBranch: "main"
# pushBranch: branch name to push changes to after task completion
# pushBranch: "feature/my-change"
# maxTurns: override Agent's defaultMaxTurns (range: 1-1000)
maxTurns: 100
# allowedTools: override Agent's defaultAllowedTools
allowedTools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
# disallowedTools: deny specific tools (takes precedence over allowedTools)
disallowedTools:
- WebFetch
# allowBash: override Agent's defaultAllowBash
allowBash: true
# timeout: max duration before the task is terminated
timeout: "30m"
# priority: queue ordering (0-1000, higher = more urgent, default: 500)
priority: 600
# sessionRef: conversation continuity
sessionRef:
name: my-session
create: true
# secretRef: override Agent's secretRef for this task
# secretRef:
# name: different-api-key
Permission Resolution
Task-level settings override Agent-level defaults. disallowedTools always takes precedence over allowedTools.
Agent.spec.runtime (defaults)
└─► Task.spec.agentRuntime (overrides)
└─► disallowedTools (always wins)
Runtime Isolation
Agent worker pods can opt into stronger sandboxing through Kubernetes RuntimeClass using the shared spec.execution field on both Agents and Tasks.
apiVersion: core.orka.ai/v1alpha1
kind: Task
metadata:
name: isolated-review
spec:
type: agent
agentRef:
name: claude-agent
prompt: "Review the repo for security issues"
execution:
runtimeClassName: gvisor
nodeSelector:
sandbox-runtime: gvisor
tolerations:
- key: sandbox-runtime
operator: Equal
value: gvisor
effect: NoSchedule
Agent.spec.executionsets defaults for all tasks using that Agent.Task.spec.executionoverrides the Agent and replacesnodeSelector,tolerations, andaffinitywhen set.gvisoris the recommended first isolation profile for Linuxkindand other containerd-based development clusters.kata-qemuuses the same API, but is best suited tominikubeor production clusters with virtualization-capable nodes.- The controller itself can remain on the default runtime; only worker Jobs need the isolation runtime.
Durable Agent Sandbox Workspaces (Experimental)
For durable or retained coding environments, agent Tasks can request Task.spec.execution.workspace. That request is separate from the git checkout settings in Task.spec.agentRuntime.workspace below. When the controller feature is enabled, Orka validates the request, passes the resolved sandbox settings to the agent worker Job, and the worker wrapper claims an upstream agent-sandbox workspace before running the configured agent runtime inside it. For reusePolicy: session, Orka derives a deterministic sandbox claim name so separate worker Jobs in the same namespaced session/template scope can reattach when the workspace is retained.
See Agent Sandbox Workspaces for the supported fields, controller flags, Helm values, and current limitations.
Workspace Management
Agent tasks can clone a git repository into the worker pod's /workspace directory.
Public Repositories
agentRuntime:
workspace:
gitRepo: "https://github.com/example/public-repo.git"
branch: "main"
Private Repositories
Create a Secret with git credentials, then reference it:
kubectl create secret generic git-credentials \
--from-literal=username=oauth2 \
--from-literal=password=ghp_your_token
agentRuntime:
workspace:
gitRepo: "https://github.com/example/private-repo.git"
branch: "feature/fix-tests"
gitSecretRef:
name: git-credentials
Note: For the Copilot runtime,
GITHUB_TOKENfrom the Agent'ssecretRefcan authenticate both the CLI and git clone operations. For the Claude and Codex runtimes, a separategitSecretRefis usually needed because their API keys do not authenticate git operations.
Codex caveat: The current Codex runtime implementation requires
defaultAllowBash: true(or task-levelallowBash: true). If bash is disabled, the worker fails fast instead of launching Codex, because the current Codex CLI does not expose a reliable shell-disable mode.
SubPath
Restrict the agent's workspace to a subdirectory of the cloned repository:
agentRuntime:
workspace:
gitRepo: "https://github.com/example/monorepo.git"
subPath: "services/api"
Specific Commit or Tag
Use ref instead of branch to check out a specific commit SHA or tag:
agentRuntime:
workspace:
gitRepo: "https://github.com/example/repo.git"
ref: "v1.2.3"
Push Changes to a Branch
Use pushBranch to have the worker commit and push changes automatically at the end of the task.
For fork-based workflows, also set forkRepo and prBaseBranch.
agentRuntime:
workspace:
gitRepo: "https://github.com/upstream/repo.git"
forkRepo: "https://github.com/my-user/repo.git"
prBaseBranch: "main"
pushBranch: "feature/my-change"
Session Continuity
Sessions enable multi-turn conversations across tasks. Session data is stored in SQLite with a normalized schema.
How Sessions Work
- Sessions store user and assistant messages only (the lowest common denominator across runtimes)
- Cross-runtime continuation is supported: a
type: aisession can be continued by atype: agenttask and vice versa - Agent-specific metadata (token counts, message counts) is tracked in the session record
- Full agent transcripts are logged to pod stdout but not stored in the session (keep sessions focused)
- Sessions enforce serial execution: only one task can hold a session lock at a time
- Session transcripts are delivered to worker pods via an init container that fetches from the controller's internal API
Using Sessions
apiVersion: core.orka.ai/v1alpha1
kind: Task
metadata:
name: follow-up-task
spec:
type: agent
agentRef:
name: claude-agent
prompt: "Now add error handling to the code you wrote"
sessionRef:
name: my-session
create: true # Create the session if it doesn't exist
append: true # Append this task's messages to the transcript (default: true)
maxMessages: 50 # Max messages to load from history (default: 50)
Session Storage
Sessions are stored in the controller's SQLite database with a normalized schema:
- Session record: metadata (name, namespace, type, active task, token counts, timestamps)
- Session messages: individual transcript entries (role, content, timestamp)
Security
All agent worker pods run with a hardened security context:
| Setting | Value |
|---|---|
| Run as non-root | uid 1000 |
| Read-only root filesystem | true |
| Capabilities | All dropped |
| Seccomp profile | RuntimeDefault |
| Privilege escalation | Disabled |
If spec.execution.runtimeClassName is set, the worker pod is also routed through the selected Kubernetes RuntimeClass while keeping the same pod and container security defaults.
Writable directories are provided via emptyDir volumes:
| Mount | Purpose |
|---|---|
/tmp | Temporary files |
/home/worker | CLI config and cache (HOME) |
/workspace | Git clone target and working directory |
Tool Permissions
| Tool | Default | Risk Level |
|---|---|---|
| Read | Allowed | Low |
| Glob | Allowed | Low |
| Grep | Allowed | Low |
| WebSearch | Allowed | Low |
| WebFetch | Allowed | Medium |
| Write | Allowed | High |
| Edit | Allowed | High |
| Bash | Allowed | High |
All tools are allowed by default for autonomous operation. To restrict high-risk tools, set defaultAllowBash: false on the Agent or allowBash: false on individual Tasks.
For Codex specifically, bash-disabled tasks are not currently supported. Use defaultAllowBash: true for Codex Agents until the upstream CLI exposes a reliable shell-disable mode.
Secrets
API keys are injected as environment variables from Kubernetes Secrets. They are never logged or stored in Task specs.
# Claude runtime
kubectl create secret generic claude-api-key \
--from-literal=ANTHROPIC_API_KEY=sk-ant-...
# Codex runtime
kubectl create secret generic codex-api-key \
--from-literal=OPENAI_API_KEY=sk-proj-...
# Copilot runtime
kubectl create secret generic copilot-token \
--from-literal=GITHUB_TOKEN=ghp_...
Controller Configuration
The controller accepts flags to configure agent worker images:
| Flag | Default | Description |
|---|---|---|
--copilot-worker-image | ghcr.io/sozercan/orka/agent-worker-copilot:latest | Container image for Copilot agent workers |
--claude-worker-image | ghcr.io/sozercan/orka/agent-worker-claude:latest | Container image for Claude agent workers |
--codex-worker-image | ghcr.io/sozercan/orka/agent-worker-codex:latest | Container image for Codex agent workers |
Example:
orka-controller \
--copilot-worker-image=ghcr.io/sozercan/orka/agent-worker-copilot:v1.0.0 \
--claude-worker-image=ghcr.io/sozercan/orka/agent-worker-claude:v1.0.0 \
--codex-worker-image=ghcr.io/sozercan/orka/agent-worker-codex:v1.0.0
Optimizing Agent Performance
Research on LLM agent context (arxiv 2602.11988) shows that verbose instructions increase token costs without proportional quality gains. Apply these guidelines to Agent and Task configuration:
- Minimal tool allowlists: Only grant tools the task actually needs. A read-only analysis task should use
allowedTools: [Read, Glob, Grep]— don't includeWrite,Edit, orBashif the task doesn't require them. Fewer tools means less prompt overhead and a smaller attack surface. - Appropriate
maxTurns: Set lower values (10–30) for focused tasks like single-file edits, and higher values (50–100+) for complex multi-file refactors. Overly generous limits waste compute on unnecessary iterations if the agent gets stuck. - Concise system prompts: Include only tooling commands, hard requirements, and non-discoverable gotchas. Codebase overviews and redundant documentation increase reasoning tokens by 14–22% without improving outcomes. See Context Engineering Best Practices for detailed guidance.
Examples
Complete sample manifests are available in config/samples/:
| File | Description |
|---|---|
core_v1alpha1_agent_codex.yaml | Agent configured for Codex CLI |
core_v1alpha1_agent_claude.yaml | Agent configured for Claude Code CLI |
core_v1alpha1_task_agent.yaml | Basic agent task with workspace |
core_v1alpha1_task_agent_copilot.yaml | Agent task using Copilot runtime |
core_v1alpha1_task_agent_workspace.yaml | Agent task with full workspace configuration |
Complete Example Flow
# 1. Create the API key secret
kubectl create secret generic claude-api-key \
--from-literal=ANTHROPIC_API_KEY=sk-ant-your-key
# 2. Create the Agent
kubectl apply -f - <<EOF
apiVersion: core.orka.ai/v1alpha1
kind: Agent
metadata:
name: claude-agent
spec:
model:
name: "claude-sonnet-4-20250514"
systemPrompt:
inline: "You are a senior software engineer."
secretRef:
name: claude-api-key
runtime:
type: claude
defaultMaxTurns: 50
defaultAllowBash: true
defaultAllowedTools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
EOF
# 3. Create a Task that clones a repo and works on it
kubectl apply -f - <<EOF
apiVersion: core.orka.ai/v1alpha1
kind: Task
metadata:
name: fix-tests
spec:
type: agent
agentRef:
name: claude-agent
prompt: "Fix the failing CI tests in the api/ directory"
agentRuntime:
workspace:
gitRepo: "https://github.com/example/my-project.git"
branch: "main"
maxTurns: 100
timeout: "30m"
priority: 600
EOF
# 4. Watch the task progress
kubectl get task fix-tests -w
# 5. Get the result
curl http://localhost:8080/api/v1/tasks/fix-tests/result \
-H "Authorization: Bearer $(kubectl create token orka-client)"
# 6. Check worker pod logs for full transcript
kubectl logs -l job-name=$(kubectl get task fix-tests -o jsonpath='{.status.jobName}')
Troubleshooting
Task stuck in Pending
- Missing Secret: Verify the Secret exists and contains the expected key (
ANTHROPIC_API_KEYorGITHUB_TOKEN).kubectl get secret claude-api-key -o jsonpath='{.data}' | keys - Session locked: Another task may hold the session lock. Check via the REST API:
curl http://localhost:8080/api/v1/sessions/<name> \-H "Authorization: Bearer $(kubectl create token orka-client)"
- Agent not found: Verify the Agent exists and has
runtimeconfigured:kubectl get agent claude-agent -o yaml
Task fails immediately
- Type mismatch:
type: agenttasks require an Agent withruntimeconfigured.type: aitasks cannot use Agents withruntime. - Invalid runtime type:
runtime.typemust becopilot,claude, orcodex. - Worker image not available: Check that the worker image is accessible from your cluster:
kubectl describe pod -l orka.ai/worker-type=agent
Result too large
Task results are stored in SQLite, which has no practical size limit. If the agent produces a very large output:
- The final text result is stored; full transcripts are logged to pod stdout only
- Check pod logs for the complete output:
kubectl logs <pod-name>
Pod in CrashLoopBackOff
- Check pod logs for CLI errors:
kubectl logs <pod-name> --previous
- Verify the API key is valid and has sufficient permissions
- Ensure the worker image includes the expected CLI binary