Skip to main content

Brain layer for Kagura harnesses — headless CLI coding-agent launcher (claude -p today), subscription-auth hygiene, verdict, doctor primitives

Project description

kagura-brain

The provider-neutral "brain" layer shared by Kagura's CLI-brain harnesses (kagura-engineer, kagura-planner, kagura-code-reviewer).

These tools run a headless CLI coding agent as their brain. They were each re-implementing the same seams: launching the agent, stripping stale provider credentials so subscription auth wins, parsing exit codes and sentinel markers, and normalizing output. This package centralizes those seams.

Two adapters ship today — Claude Code (claude -p) and Codex CLI (codex exec) — as thin siblings over one shared launcher core (core._run + verdict + extract_block). Each strips its provider's credential/endpoint overrides from the child env so the CLI's subscription login wins: claude deny-sets ANTHROPIC_*; codex prefix-scrubs OPENAI_*/CODEX_* (including OPENAI_BASE_URL and CODEX_HOME).

from kagura_brain import claude, codex

claude.invoke("…prompt…", mcp_config=".mcp.json")   # claude -p
codex.invoke("…prompt…", sandbox="read-only")       # codex exec

MCP / approval differs by provider. Claude takes per-call --mcp-config / --allowedTools (see claude.mcp_args). Codex manages MCP servers persistently via codex mcp / ~/.codex/config.toml (no per-call flag), and its sandbox / approval is opt-in: pass sandbox= (read-only | workspace-write | danger-full-access) or bypass_approvals=True — neither is loosened by default.

BYO endpoint (opt-in)

By default both adapters strip the provider's endpoint/credential env so the subscription login wins. To deliberately route at a caller-chosen endpoint (Ollama Cloud / any compatible gateway), pass endpoint + api_key together — they are injected after the scrub, so only these explicit values reach the child while an ambient *_BASE_URL override stays stripped (#2):

# Codex → Ollama Cloud (OpenAI-compatible). "ollama-cloud" is an alias for
# codex.OLLAMA_CLOUD_ENDPOINT ("https://ollama.com/v1").
codex.invoke("…prompt…", endpoint="ollama-cloud", api_key="…")
# Codex → a LOCAL ollama/lmstudio backend (no endpoint/key needed):
codex.invoke("…prompt…", local_provider="ollama")
# Claude → a caller-supplied Anthropic-compatible gateway (no Ollama preset:
# Ollama Cloud is OpenAI-, not Anthropic-, compatible):
claude.invoke("…prompt…", endpoint="https://my-gateway/v1", api_key="…")

Supplying only one of endpoint/api_key raises ValueError; a non-https endpoint emits a UserWarning (prompt + code context goes off-box). With none of these set, the default subscription-auth path is byte-for-byte unchanged.

Provider-neutral selector

When a consumer supports more than one backend, select confines the claude/codex dispatch — and the per-provider MCP wiring — to the library, so each consumer no longer re-encodes it (#14):

import os

from kagura_brain import select, BRAIN_API_KEY_ENV

# "claude" (default) and "codex" are both supports_mcp=True.
handle = select(cfg.backend, endpoint=cfg.endpoint, api_key=os.environ.get(BRAIN_API_KEY_ENV))
handle.invoke("…prompt…", cwd=repo, mcp_config=".mcp.json", allowed_tools=MEMORY_TOOLS)
# Same mcp_config/allowed_tools to both; the adapter owns the mechanism:
# claude → --mcp-config/--allowedTools per call; codex → translates the .mcp.json
# into -c mcp_servers.* overrides and ignores allowed_tools (no codex analog).
# endpoint/api_key forward to both.

select takes primitives, never a consumer's Config, and never reads the env itself — the library owns only the standard name BRAIN_API_KEY_ENV ("KAGURA_BRAIN_API_KEY"); the consumer reads it and passes api_key= in. An unknown backend raises ValueError.

Why a separate package (not folded into the memory SDK)

Harness-support code splits cleanly along two axes:

Axis Belongs in Examples
memory kagura-memory-python-sdk sync client facade, .mcp.json setup, auth resolution, recall
brain this package CLI-agent launcher (claude -p + codex exec), subscription-auth hygiene, verdict contract, doctor primitives

Pushing CLI-agent spawning into a memory SDK would invert the layers ("memory spawns the agent"). So the brain axis lives here, and this package depends on no memory package — the two support libs are mutually independent.

kagura-engineer   kagura-planner   kagura-code-reviewer
        \                |                /
         `--> kagura-brain  +  kagura-memory-python-sdk <--'
                  (brain axis)            (memory axis)

Install

pip install kagura-brain
# or: uv add kagura-brain

Requires Python 3.11+. It has no Python runtime dependencies (stdlib-only) — and by design depends on no memory package (see the axis split above).

Prerequisites: the provider CLIs

kagura-brain is a launcher — it drives the provider CLIs as subprocesses, so each adapter needs its own CLI installed and on PATH. These are external tools, not pip dependencies; install only the one(s) you use:

Adapter Needs Auth (default path)
claude.invoke() Claude Code CLI (claude) — see docs signed in to your Claude subscription (the adapter strips ANTHROPIC_* so the subscription login wins)
codex.invoke() Codex CLI (codex) — see docs codex login (ChatGPT subscription; the adapter strips OPENAI_*/CODEX_*). Verified against Codex 0.133.0 (codex._CODEX_VERIFIED_VERSION)

The CLI binary is required even in BYO-endpoint mode — only the auth source changes: instead of the subscription login, the caller-supplied endpoint + api_key (or, for Codex, a local --oss --local-provider backend) are used. No subscription login is needed for the BYO path, but claude / codex must still be installed.

doctor primitives to check CLI launchability are planned (see Status).

Status

Public surface is built incrementally under TDD, one consumer migration per PR:

  • core — shared seam: BrainResult, _run (subprocess + env-scrub + timeout + utf-8 decode), as_text, extract_block
  • claude.invoke() — headless claude -p launcher (ANTHROPIC_*/CLAUDE_* deny-set, ---guarded prompt, mcp_args, opt-in BYO endpoint/api_key)
  • codex.invoke() — headless codex exec launcher (OPENAI_*/CODEX_* prefix scrub, ---guarded prompt, opt-in sandbox, BYO endpoint/api_key + local_provider)
  • verdictPROCEED set + exit-code map (contract only)
  • doctor — provider-neutral check primitives (check_binary, check_auth, check_endpoint, aggregate) + presence-only claude.check()/codex.check() wrappers
  • select — provider-neutral BrainHandle selector over the adapters (supports_mcp capability; per-provider MCP wiring confined to the library — claude per-call flags, codex -c mcp_servers.*; BRAIN_API_KEY_ENV name)

Development

uv sync --extra dev
uv run pytest          # tests
uv run ruff check .    # lint
uv run ruff format .   # format
uv run mypy            # type check

See CONTRIBUTING.md for the full workflow and CHANGELOG.md for release history.

License

Apache-2.0. See LICENSE and NOTICE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kagura_brain-0.4.0.tar.gz (79.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kagura_brain-0.4.0-py3-none-any.whl (31.2 kB view details)

Uploaded Python 3

File details

Details for the file kagura_brain-0.4.0.tar.gz.

File metadata

  • Download URL: kagura_brain-0.4.0.tar.gz
  • Upload date:
  • Size: 79.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kagura_brain-0.4.0.tar.gz
Algorithm Hash digest
SHA256 ea9a538655bfa1e5ea1432343fcc079ea8c5c4026d2251c2101a0e8ce41e7466
MD5 7d755df5cdeb64967dfe5cd7c79ab68c
BLAKE2b-256 7c65f97d077a12f0221bfc0d636892e30f6fb8434549018f9614931b635dd1c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for kagura_brain-0.4.0.tar.gz:

Publisher: publish.yml on kagura-ai/kagura-brain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kagura_brain-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: kagura_brain-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 31.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kagura_brain-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aa7dbf27a7cd349abc205221e5195ef7a2690720ff252178cc057578256fbc79
MD5 d03d292c8335ec0277d9a8f5172a119c
BLAKE2b-256 c5827564bd0e2456aab4c7e0e0c4a79473105bff9a5e02d19fa7706ebcfed6ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for kagura_brain-0.4.0-py3-none-any.whl:

Publisher: publish.yml on kagura-ai/kagura-brain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page