Harnesses

The harness is the runtime that executes your agent loop. Swap one line to switch runtimes.

executor:
  harness: claude-sdk

Tools, policies, prompts, and models stay the same across harnesses — only the runtime underneath changes.

Two ways to run a harness

Most coding agents can run in one of two modes:

Supported harnesses

AgentDirectNative TUI
Claude Codeclaude-sdk (alias claude)claude-native
Codexcodexcodex-native
Cursorcursorcursor-native
Antigravityantigravityantigravity-native
Goosegoosegoose-native
Qwen Codeqwen (alias qwen-code)qwen-native
Kimikimi (alias kimi-code)kimi-native
Hermeshermeshermes-native
Pipipi-native
OpenCodeopencode-native (alias opencode)
Kirokiro-native
Copilotcopilot
OpenAI Agents SDKopenai-agents (alias openai-agents-sdk)

Pi is a headless multi-model worker that runs on any gateway model — ideal for review, exploration, and read-heavy tasks delegated by a supervisor agent.

Custom ACP agents

Beyond the agents above, the generic acp harness drives any agent that speaks the Agent Client Protocol — the open, editor-agnostic protocol used by Gemini CLI, Qwen Code, Goose, Zed's Claude Code bridge, and in-house agents. You point Omnigent at a launch command and it speaks ACP against whatever that command starts.

Each ACP agent brings its own auth — Omnigent stores no credential, so log into the agent through its own CLI first. Register agents with omnigent setupconfigure harnessesCustom ACP agentAdd, providing a name, a launch command, and an optional model. Some paste-ready commands:

AgentCommand
Gemini CLIgemini --experimental-acp
Qwen Codeqwen --acp
Goosegoose acp
Claude Codenpx -y @zed-industries/claude-code-acp

Each registered agent is stored in a top-level acp: block of ~/.omnigent/config.yaml and gets a stable slug derived from its name. It then surfaces as its own harness id, acp:<slug>, in the web picker and in agent YAML:

acp:
  agents:
    - { name: Gemini CLI,  command: gemini --experimental-acp }
    - { name: Claude Code, command: npx -y @zed-industries/claude-code-acp }
    - { name: Goose,       command: goose acp, model: gpt-5.3 }
executor:
  harness: acp:gemini-cli

The agent runs its own agent loop, tools, and context window; Omnigent renders its streaming output, reasoning, and tool cards, routes its permission requests through your contextual policies as web elicitation cards, and honors interrupts. Omnigent also exposes its own builtin tools (session, sub-agent, skill, and policy tools) to the agent alongside the agent's native tools; set OMNIGENT_ACP_MCP=0 to disable that bridge.

Note: The generic ACP harness has no fixed binary — each agent owns its own install and login, so a missing binary is a hint, not a hard gate. A sandboxed generic ACP agent gets read access to its binary directory, the cwd, and write access to /tmp; an agent that must write its own config directory needs sandbox: none (the default) for now.

Swap harnesses

Tools, policies, and other config stay the same across harnesses. Just change the harness value in your YAML, or override it at runtime:

omni run agent.yaml --harness codex

See Models & Credentials for how to set up API keys and choose models.

Community harnesses

The built-in harnesses above ship with pip install omnigent. Beyond those, Omnigent discovers additional harnesses at startup through a plugin registry, so the community can add support for a new runtime as a separate package — without changing the core omnigent package.

pip install omnigent          # core harnesses only
pip install omnigent-foo      # adds the `foo` harness to the same omni CLI

An installed plugin's harness shows up everywhere a built-in one does: it's accepted in agent YAML, honored by --harness, and merged into the harness picker in the web UI.

Build a plugin

A harness plugin is a Python package that declares an entry point in the omnigent.community.harness group and exports a get_contribution() function. Implementation modules live under the omnigent.community.harness.* namespace.

# pyproject.toml
[project]
name = "omnigent-foo"
dependencies = ["omnigent"]

[project.entry-points."omnigent.community.harness"]
foo = "omnigent.community.harness.foo.plugin:get_contribution"
# omnigent/community/harness/foo/plugin.py
from omnigent.harness_plugins import HarnessContribution
from omnigent.harness_install_spec import HarnessInstallSpec


def get_contribution() -> HarnessContribution:
    return HarnessContribution(
        name="omnigent-foo",
        valid_harnesses=frozenset({"foo"}),
        harness_modules={
            "foo": "omnigent.community.harness.foo.harness",
        },
        aliases={"foo-code": "foo"},
        harness_labels={"foo": "Foo"},
    )

Each harness module exports create_app() -> FastAPI; the runner imports it to launch the harness. Keep top-level imports in plugin.py light — entry-point discovery runs early, so put heavy imports inside the callables that need them.

Note: Core rejects plugins that register flat package paths or try to override a built-in harness name. Community native-TUI harnesses aren't pluggable yet — the plugin interface covers direct and headless harnesses.

See the harness plugin interface design doc for the full plugin contract, including install/auth metadata, model-override env vars, and per-spawn environment builders.