# kagent Harnesses Compared: kagent vs Claude Code vs Codex vs BYO

> The four kagent 1.0 harnesses side by side: what each runs, which model providers it takes, what it drops from an AgentTemplate, and how to pick one.

- Canonical URL: https://webofmike.com/kagent-harnesses-compared/
- Author: Mike Moore (https://webofmike.com/about/)
- Published: 2026-11-03
- Last modified: 2026-10-30
- Tags: AI Agents, Kubernetes, Platform Engineering
- Cite as: Mike Moore, "kagent Harnesses Compared: kagent vs Claude Code vs Codex vs BYO", Web of Mike (webofmike.com), 2026-11-03. https://webofmike.com/kagent-harnesses-compared/


Short version: kagent has four harnesses, and the one you pick decides what runs your agent and how much of kagent it gets to use. My [Claude Code harness post](/kagent-v1-agentinstance-claude-code-harness/) covers one of them. This is the map of all four.

*Disclosure: I work at Solo.io, which created kagent (now an open-source project) and sells Solo Enterprise for kagent. This post is built from the public [Solo Enterprise for kagent harness docs](https://docs.solo.io/kagent/1.0.x/agents/agent-harness/) as of 2026-10-30. kagent 1.0 is alpha, so field names can still move.*

## What a Harness is

A Harness is the Kubernetes resource that says *how* an agent is allowed to run: which runtime, which image, and which Agent Substrate worker pool and snapshot bucket. It runs nothing by itself. An **Agent** pairs one Harness (`spec.harnessRef`) with one **AgentTemplate** (prompt, model, tools), and the controller compiles that pair into an immutable, digest-identified revision. For the bigger picture, see [what a cloud-native agent harness is](/what-is-a-cloud-native-agent-harness/) and [Agent Substrate](/kagent-agent-substrate/).

## The four harnesses

| Harness | What it runs | Use it when |
|---|---|---|
| `kagent` | kagent's built-in Go engine | You want a declarative agent (prompt, skills, plugins, MCP) and the widest feature set |
| `claude` | Claude Code | You want Claude doing the loop, on Anthropic or Bedrock |
| `codex` | Codex | You want Codex doing the loop, on OpenAI or Bedrock `gpt-*` |
| `byo` | Your own image implementing kagent's A2A contract | You already built the agent in another framework |

Deep dives: [Codex harness](/kagent-codex-harness/) · [Claude Code harness](/kagent-v1-agentinstance-claude-code-harness/) · BYO and native kagent harness posts coming next.

## Model providers

| Provider | kagent | byo | codex | claude |
|---|---|---|---|---|
| OpenAI | ✅ | ✅ | ✅ | ❌ |
| Anthropic | ✅ | ✅ | ❌ | ✅ |
| Bedrock | ✅ | ✅ | ✅ | ✅ |
| AzureOpenAI, Gemini, Mistral, Ollama, Foundry | ✅ | ✅ | ❌ | ❌ |
| AnthropicVertexAI, GeminiVertexAI, SAPAICore | ❌ | ❌ | ❌ | ❌ |

The last row is a design choice, not a gap someone forgot. kagent reaches models through an egress gateway that injects the credential as a header. Vertex needs a mounted service-account file and SAP AI Core does its own OAuth exchange, so neither fits. Same reason Bedrock wants an `AWS_BEARER_TOKEN_BEDROCK` key, not IAM access keys.

## What each harness drops

Claude Code and Codex run their own agentic loops, so they can't take everything an AgentTemplate offers.

| Constraint | Applies to |
|---|---|
| Structured output rejected | codex, claude, byo |
| MCP `tokenPassthrough` rejected | codex, claude |
| ModelConfig with `defaultHeaders`, `tls` or `tokenPassthrough` rejected | codex, claude |
| Subagents can't carry their own tools/skills and must share provider + creds | codex, claude |
| MCP server must be `STREAMABLE_HTTP` (SSE rejected) | codex |
| Partial MCP tool selection binds the whole server (warning, not error) | claude |
| File attachments in the kagent UI chat | kagent only |

That Claude one is worth caring about. If you bound three tools from an MCP server, the agent gets all of them. It shows up in `status.warnings`, and a lot of people won't look there. If tool scoping matters, enforce it at the gateway too.

## Rules every harness shares

- Images pinned by `sha256` digest. A bare tag is rejected. Omit the image on kagent/codex/claude to get the release's built-in one.
- A WorkerPool and snapshot location are required. A missing WorkerPool (`WorkerPoolNotFound`) is the most common failure.
- At most 32 env vars per Actor, 32,768 chars per value, and kagent's own variables count against that.
- CA trust variables (`SSL_CERT_FILE`, `NODE_EXTRA_CA_CERTS`, etc.) are reserved, because the egress gateway intercepts HTTPS.
- Credentials don't go in `env`. They live in a ModelConfig or RemoteMCPServer.

## How to tell if it worked

Check the Agent, not the Harness. A Harness has no status of its own, so its `READY` column is always empty.

```bash
kubectl describe agent <agent-name> -n kagent
```

Look at `ResolvedRefs` (does everything exist), `Compatible` (does the harness accept this config) and `Ready` (is capacity up).

## My take

Default to `kagent`. Reach for `claude` or `codex` when you specifically want that loop's behavior and you can live with whole-server MCP binding or Streamable-HTTP-only tools. Use `byo` when the agent already exists and rewriting it isn't worth it. Whichever you choose, the harness is a policy object, so pick it the way you'd pick a security boundary.

