fracta.yaml, how auth is wired for local and K8s deployments, and how to set up K8s manifests for non-Claude runtimes.
For adding a new runtime from scratch, see host-onboarding.md.
For deployment mode architecture, see deployment-modes.md.
Runtime Capabilities
| Capability | Claude | Codex | OpenCode |
|---|---|---|---|
| Batch mode | Yes | Yes | Yes |
| Stream mode | Yes | Yes (app-server JSON-RPC) | Yes (serve HTTP+SSE) |
| Agent MCP | Yes | Yes (.codex/config.toml) | Yes (opencode.json) |
| Resume token | Yes (session ID) | Yes (thread ID) | Yes (session ID) |
| Tool permissions | Yes (settings.json) | Yes (—full-auto) | Yes (opencode.json) |
| Structured events | Yes | Yes (JSONL) | Yes (nd-JSON) |
| turn/steer | No | Yes (TurnSteerer) | No |
| K8s batch | Job | Job | Job |
| K8s stream | N/A (local only) | Pod (WebSocket) | Pod (HTTP+SSE) |
fracta.yaml Configuration
Basic: Local Development
runtimes: map still load for compatibility, but new configs should use agents.agent_runtimes.
Key Fields
| Field | Purpose |
|---|---|
adapter | Which runtime implementation to use (claude, codex, opencode) |
model | Default model for this runtime (overridden by tier or per-spawn) |
model_tiers | Named shortcuts: heavy, medium, light → specific model IDs |
env | Environment variables injected into local agent processes |
auth_profile | References a profile under auth.credentials.profiles |
auth_binding | Per-runtime override of the credential binding (rare) |
kubernetes.env | K8s-specific env vars (from Secrets/ConfigMaps) |
kubernetes.image | Per-runtime container image override |
Spawning with a Specific Runtime
--host-type flag is deprecated but still accepted.
Authentication
Auth configuration lives in theauth.credentials.profiles section. Each runtime references a profile by name via auth_profile. The credential system is runtime-agnostic — the same profile structure works for all runtimes. What differs is the binding type and the env vars each runtime expects. For the canonical reference on binding types, credential source types, profile layout, and which names are schema keywords versus local labels versus external env/Secret names, see credential-pipeline.md.
Claude (Bedrock)
Claude Code authenticates via Bedrock. The credential pipeline:- A runtime auth resolver (command) runs inside the agent to get a bearer token
- The token is injected via a claude_api_key_helper binding into Claude’s
settings.json - Required env vars:
CLAUDE_CODE_USE_BEDROCK,CLAUDE_CODE_SKIP_BEDROCK_AUTH,AWS_REGION - Forbidden:
CLAUDE_CODE_SIMPLE(disables settings.json loading entirely)
Codex (OpenAI API Key)
Codex authenticates viaOPENAI_API_KEY. Two approaches:
Local — env var injection:
secret_ref creates a K8s envFrom mount in the agent pod. No command resolver needed — the key is static.
OpenCode (Bedrock Bearer Token)
OpenCode uses Anthropic models via Bedrock. It readsAWS_BEARER_TOKEN_BEDROCK directly (no settings.json indirection like Claude).
Local-process — credential pipeline with command_output:
AWS_BEARER_TOKEN_BEDROCK.
Model ID note: For Bedrock in ap-southeast-2, OpenCode model IDs must use the au. prefix (e.g. amazon-bedrock/au.anthropic.claude-sonnet-4-6). OpenCode auto-generates apac. for this region which is invalid.
Important limitation: OpenCode does not have a Claude-style runtime helper projection. A runtime-only source such as http_header_token with scope: agent_runtime does not populate AWS_BEARER_TOKEN_BEDROCK by itself today. OpenCode currently needs a concrete token value at spawn time.
Key difference from Claude auth: Claude uses claude_api_key_helper binding and can re-run the helper on TTL. OpenCode uses bearer_env binding and gets a point-in-time token value in AWS_BEARER_TOKEN_BEDROCK.
OpenCode (OpenAI Key — Alternative)
OpenCode also supports OpenAI models. Same pattern as Codex:K8s Deployment
Batch Mode (Jobs)
All three runtimes work as K8s Jobs out of the box. The controlplane config needs the runtime entries in the ConfigMap:WriteWorkspace automatically creates the correct config files in the agent workspace:
- Claude:
.claude/settings.json(MCP + permissions) - Codex:
.codex/config.toml(MCP gateway endpoint) - OpenCode:
opencode.json(MCP + permissions +task:deny)
Stream Mode (Long-lived Pods)
Stream mode uses persistent Pods instead of Jobs. The orchestrator automatically:- Launches a Pod running the runtime’s serve command
- Waits for readiness (TCP probe for Codex, HTTP probe for OpenCode)
- Connects the
StreamSessionover the network
- Command:
codex app-server --listen ws://0.0.0.0:8080 - Transport: WebSocket (JSON-RPC)
- Auth: Capability token generated per-session, injected as env var
- Readiness: TCP socket probe on port 8080
- No liveness HTTP endpoint (app-server has none)
- Command:
opencode serve --port 4096 --hostname 0.0.0.0 - Transport: HTTP REST + SSE
- Auth: Password generated per-session, basic auth on all HTTP calls
- Readiness:
GET /global/health:4096returns 200 - Env:
OPENCODE_SERVER_PASSWORD,OPENCODE_DB(emptyDir path),OPENCODE_CONFIG_CONTENT(config as env)
Per-Runtime Container Images
If runtimes need different base images (common when OpenCode/Codex aren’t in the shared agent image):OpenCode Safety: Subagent Monitoring
OpenCode has no equivalent to Claude’sCLAUDE_CODE_MAX_TURNS. To prevent runaway subagent spawning:
task:denypermission — Written byWriteWorkspaceintoopencode.json. Blocks thetasktool (subagent spawning) by default.- Step count monitoring — The
ServeSessioncountsstep_startSSE events during eachSend()call. Warnings are logged at milestones (5, 10, 15, 20). If the count exceeds the threshold (default: 20), the session is aborted viaPOST /session/:id/abort.
RuntimeEntry in a future iteration.

