Install the omnigent policy
The cardinal-omnigent-policy package is what puts sessions run through the omnigent meta-harness on the Agent Outcomes dashboard. Unlike the CLI plugins, this one is a pip package that loads inside the omnigent server process as a policy module — the same server that runs your Claude, Codex, Cursor, Hermes, Pi, OpenCode, or custom-YAML agents.
- Telemetry — every conversation the omnigent server handles streams per-turn token and tool usage to Cardinal, attributed to engineer, repo, branch, and initiative for the dashboard’s cost and anti-pattern analysis.
- Enforced spend limits — omnigent runs the policy at the
requestphase, which isFAIL_CLOSED— any spend-limit policy your org has set is enforced in-flight (a block verdict stops the request). Plus an optional omnigent-native per-session hard cap (session_cost_limit_usd).
Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.
Requirements
- omnigent installed (any recent alpha; the adapter is drift-tested against a pinned upstream commit — see the adapter README ).
- Python 3.12+ (omnigent’s requirement — the policy inherits it).
- A Cardinal account on
app.cardinalhq.io, or a self-hosted Maestro your operator has prepared (see Connect AI clients).
1. Install
The policy has to load inside the same Python interpreter that runs your omnigent server — so where you install it depends on how omnigent itself is installed. cardinal-agent-core is pulled in as a dependency.
Homebrew / macOS system Python users: a bare pip install cardinal-omnigent-policy will fail with error: externally-managed-environment (PEP 668) — Homebrew’s Python refuses system-wide installs. Use pipx inject or uv tool install --with (below, if omnigent is pipx- or uv-tool-installed), or a virtualenv. Never use --break-system-packages.
Recommended — pipx-installed omnigent:
pipx install omnigent # if you don't have it yet
pipx inject omnigent cardinal-omnigent-policy --include-apps--include-apps puts the cardinal-omnigent-connect CLI on your PATH. If you already injected an older version, add --force.
uv-tool-installed omnigent:
uv tool install omnigent --python 3.12 \
--with cardinal-omnigent-policy \
--with-executables-from cardinal-omnigent-policy--with is uv’s equivalent of pipx inject — it adds the policy (and cardinal-agent-core) into omnigent’s own tool environment. --with-executables-from is the equivalent of pipx’s --include-apps; without it, cardinal-omnigent-connect is installed but not exposed on your PATH.
Pin the interpreter. Pass --python matching the version omnigent’s tool environment already uses. Re-running uv tool install omnigent without --python makes uv rebuild the environment on its default interpreter (it prints Ignoring existing environment … the requested Python interpreter does not match) — silently bumping the Python version underneath your server. Check the current version with uv tool list --show-version-specifiers or by inspecting ~/.local/share/uv/tools/omnigent/bin/python.
Virtualenv-installed omnigent:
source /path/to/omnigent-venv/bin/activate
pip install cardinal-omnigent-policyContainer image: add cardinal-omnigent-policy to the image’s Python dependencies and rebuild.
Sanity check the injection landed inside omnigent’s venv (not a separate one — pipx install cardinal-omnigent-policy and uv tool install cardinal-omnigent-policy are both wrong; they isolate the policy from omnigent):
# pipx
~/.local/pipx/venvs/omnigent/bin/python -c "import cardinal_omnigent, cardinal_core; print(cardinal_omnigent.__file__)"
# uv tool
~/.local/share/uv/tools/omnigent/bin/python -c "import cardinal_omnigent, cardinal_core; print(cardinal_omnigent.__file__)"The printed path should be under omnigent’s own environment (~/.local/pipx/venvs/omnigent/lib/... or ~/.local/share/uv/tools/omnigent/lib/...).
Then confirm the cardinal-omnigent-connect CLI itself landed on your PATH — this is what --include-apps (pipx) / --with-executables-from (uv) provides, and it’s separate from the import check above:
command -v cardinal-omnigent-connect # should print a path
uv tool list # (uv) lists omnigent + its injected executablesIf the import works but command -v finds nothing, you installed the policy correctly but skipped the executable flag — re-run the inject/install with --include-apps (pipx) or --with-executables-from cardinal-omnigent-policy (uv). (Note: the distribution is named cardinal-omnigent-policy but imports as cardinal_omnigent, and its cardinal-agent-core dependency imports as cardinal_core — the names above are correct.)
2. Connect
cardinal-omnigent-connect --config ~/.omnigent/config.yaml~/.omnigent/config.yaml is omnigent’s default server config — the file omnigent server reads on start and omnigent config edits. If your server runs with a custom -c/--config path, point --config at that file instead: connect merges its managed block into whichever config your server actually loads, so it must be the same one.
The command prints a URL like https://app.cardinalhq.io/connect?code=ABCD-EFGH. Open it in your browser, sign in, pick the org, and click Approve. Once approved, connect mints an ingest credential, writes the state directory, and merges a cardinalManaged-tagged block into your server config.
For self-hosted Maestro, pass your host:
cardinal-omnigent-connect --host https://maestro.example.internal --config ~/.omnigent/config.yamlThen restart the omnigent server so policy_modules: reloads and the policies pick up the new config.
3. Verify
Confirm the block was merged in:
grep -A 10 "cardinal:" ~/.omnigent/config.yamlYou should see ingest_endpoint, ingest_api_key, org, and state_dir under a cardinalManaged-tagged block, and cardinal_omnigent in policy_modules:.
Run one session through your omnigent server; it should appear on the Outcomes dashboard (sliced by harness=omnigent) within a few minutes.
Getting attributed correctly
Omnigent’s policy contract carries no workspace, repo, or branch — the server doesn’t see a filesystem the way the CLI plugins do. Initiative attribution therefore rides session labels. Stamp them in your agent specs or operator config:
labels:
cardinal.repo: "your-org/your-repo"
cardinal.branch: "feat/outcomes-observability"cardinal.branch runs through the same <type-prefix>/<kebab-name> convention (feat, fix, refactor, infra, chore, research, spike) as the CLI plugins. Sessions without labels attribute to type research with no named initiative — same as protected-branch sessions on the CLI adapters.
Mid-session git checkout -b commands from shell tools are sniffed as an enrichment fallback (the adapter watches for checkout -b/-B and switch/switch -c), so a branch cut inside a session still attributes correctly even if labels weren’t stamped.
Subagent attribution
cardinal.subagent_usage fires on the response phase of conversations whose labels mark them as sub-agent children. omnigent stamps omnigent.wrapper and id labels for its native Claude / Codex UI children automatically. For native workflow or custom-YAML sub-agents, stamp cardinal.subagent: <name> in the sub-agent spec’s guardrails.labels and it will show up as a distinct child under the parent session.
Manual config
cardinal-omnigent-connect is the easy path, but you can wire it by hand — see Registering with an omnigent server in the adapter README for the full cardinal: config surface (including the optional session_cost_limit_usd hard cap and the factory-registration form).
Privacy
The policies never see prompt contents or tool inputs/outputs. What they do capture: model, per-turn token counts and derived cost, tool names and their bash classifications (for shell tools), and session/subagent identity for attribution. Repo and branch come from the labels you stamp (or from shell branch sniffing) — nothing else on your filesystem is visible to the policies.