A lightweight, native Rust coding agent with built-in ACP support and ChatGPT subscription authentication. No Node.js, no Python, no adapter layer.
# Build
cd openab-agent && cargo build --release
# Authenticate (browser flow — recommended)
openab-agent auth codex-oauth
# Headless server (paste callback URL)
openab-agent auth codex-oauth --no-browser
# Run as ACP server (used by openab core)
openab-agent[agent]
# command defaults from OPENAB_AGENT_COMMAND="openab-agent"
# working_dir = "/home/agent" # optional — defaults to $HOME
env = { OPENAB_AGENT_OPENAI_MODEL = "gpt-5.4-mini" }A small JSON file next to auth.json (default <auth dir>/config.json,
overridable with OPENAB_CONFIG_PATH) declares the default model and params, so
a deployment can set them in a file instead of only via env vars. Secrets never
go here — credentials stay in the locked auth.json store.
Resolution is env-over-config: OPENAB_AGENT_MODEL / OPENAB_AGENT_MAX_TOKENS
override the file, so a pod's injected env stays authoritative over a baked
config. A missing file is fine (empty config); a malformed file is logged and
ignored (the agent then falls back to env / built-in defaults). Unknown keys are
tolerated for forward-compatibility.
| Variable | Default | Description |
|---|---|---|
OPENAB_AGENT_MODEL |
— (required for Anthropic) | Anthropic model id, optionally provider/-qualified (e.g. claude-opus-4-8, anthropic/claude-opus-4-8). No hardcoded default — dateless 4.6+ IDs are fixed canonical IDs that retire each generation, so the agent fails loud if unset rather than pin a model that will eventually 404. Overrides model in config.json. |
OPENAB_AGENT_OPENAI_MODEL |
gpt-5.4-mini |
Model to use (must be supported by your ChatGPT plan — see Supported Models) |
OPENAB_AGENT_OPENAI_BASE_URL |
https://chatgpt.com/backend-api |
API base URL |
OPENAB_AGENT_PROVIDER |
auto-detect | Force provider (anthropic, openai, codex) |
OPENAB_AGENT_MAX_TOKENS |
8192 |
Max output tokens. Overrides max_tokens in config.json. |
OPENAB_AGENT_OAUTH_CLIENT_ID |
Pi's client | Custom Codex OAuth client ID |
OPENAB_AGENT_ANTHROPIC_CLIENT_ID |
Claude Code's client | Custom Anthropic OAuth client ID |
OPENAB_AGENT_MAX_TOOL_LOOPS |
50 |
Max tool-call iterations per prompt before the agent gives up |
ANTHROPIC_API_KEY |
— | Anthropic API key. Highest-precedence Anthropic credential (see Anthropic credentials). |
CLAUDE_CODE_OAUTH_TOKEN |
— | Pre-provisioned long-lived Claude Pro/Max subscription token (from claude setup-token). Fleet route — no interactive login, no auth.json write. |
OPENAB_CONFIG_PATH |
<auth dir>/config.json |
Override the config-file path. |
openab-agent auth codex-oauthOpens browser to authenticate with your ChatGPT Plus/Pro subscription.
openab-agent auth codex-oauth --no-browser- Prints an authorization URL
- Open it in any browser and approve
- Browser redirects to
localhost:1455(fails on remote server) - Copy the full URL from the browser address bar
- Paste it back into the terminal
openab-agent auth codex-deviceNote: Device flow currently has limited scopes and may not work with all models.
Three ways to authenticate Anthropic, resolved in this precedence (ADR §5.3):
-
API key —
export ANTHROPIC_API_KEY=sk-ant-.... No login; auto-detected. -
Pre-provisioned subscription token (fleet route) —
export CLAUDE_CODE_OAUTH_TOKEN=...(mint once withclaude setup-token; ~1-year Claude Pro/Max token). Sent as aBearersubscription token with the Claude Code identity headers — no interactive login, noauth.jsonwrite, no refresh. Recommended for pods (inject as a k8s secret). -
Interactive Claude Pro/Max OAuth — browser PKCE login, refreshed from the stored
anthropic-oauthtenant inauth.json:openab-agent auth anthropic-oauth # browser openab-agent auth anthropic-oauth --no-browser # paste code#state
A higher-precedence source's own errors (e.g. a key set but no model) surface rather than silently falling through to a lower one.
Subscription-OAuth providers are declared as a single OAuthVendor descriptor
(auth.rs, ADR §5.1) — namespace, client id, authorize/token URLs, redirect,
scope, token-body encoding. The shared PKCE/device/refresh driver reads the
descriptor, so a new vendor is a new descriptor, not a new hand-rolled flow.
Place an AGENTS.md file in the working directory (cwd). It will be prepended to the default system prompt at session creation.
/home/agent/
├── AGENTS.md ← read at session start
├── .openab/
│ └── agent/
│ └── auth.json
│ └── skills/ ← skill directories
│ └── my-skill/
│ └── SKILL.md
└── (your project files)
openab-agent supports on-demand skills following the Agent Skills standard. Skills are directories containing a SKILL.md with YAML frontmatter.
Scanned in order (first occurrence of a name wins):
<working_dir>/.openab/skills/— project-local skills~/.openab/agent/skills/— global skills
---
name: my-skill
description: What this skill does and when to use it
---
# Instructions
Steps the agent should follow when using this skill.- At session start, openab-agent scans skill directories
- Skill names and descriptions are injected into the system prompt
- When a task matches, the agent uses
readto load the full SKILL.md - The agent follows the instructions using its built-in tools (bash, read, write, edit)
.openab/skills/
└── brave-search/
├── SKILL.md
└── search.sh
---
name: brave-search
description: Web search via Brave Search API. Use when the user needs current information from the web.
---
# Brave Search
## Usage
\`\`\`bash
./search.sh "query"
\`\`\`Skills written for Pi (~/.pi/agent/skills/) or Claude Code (~/.claude/skills/) use the same SKILL.md format. Copy or symlink them into ~/.openab/agent/skills/ to reuse.
docker build -f Dockerfile.native -t openab-native:latest .Image is ~20MB (debian-slim + static Rust binaries). No runtime dependencies.
~7MB per session — 28x lighter than Pi, 55x lighter than Kiro CLI.
gpt-5.2gpt-5.3-codexgpt-5.3-codex-sparkgpt-5.4gpt-5.4-minigpt-5.5
4 built-in tools:
read— file contents or directory listingwrite— create/overwrite fileedit— string replacementbash— shell execution with process group isolation
{ "model": "anthropic/claude-sonnet-4-6", // single provider/model string "max_tokens": 8192 // optional }