BYOA Runtime is a local-first daemon for running user-owned coding agents behind one durable, versioned API. A team orchestrator can ask a machine to run Codex, Claude Code, or Kimi Code without receiving that user's model-provider keys or depending on each vendor's process protocol.
team control plane --outbound authenticated WebSocket--> BYOA Runtime
|-- Codex adapter
|-- Claude Code adapter
`-- Kimi Code ACP
The stable boundary is the daemon's task/event protocol. ACP and the pinned agent adapters are replaceable implementation details:
- Codex via
@agentclientprotocol/codex-acp - Claude Code via
@agentclientprotocol/claude-agent-acp - Kimi Code via its native
kimi acpcommand
Status: early release. The daemon runs agents with the privileges of your local OS account; it is not an operating-system sandbox.
- One validated task schema and normalized event stream for all three agents.
- Local HTTP plus SSE, and an outbound authenticated WebSocket for a control plane. No inbound firewall opening is required for remote orchestration.
- SQLite-backed idempotency, leases, restart recovery, execution attempts, and fencing tokens.
- At-least-once remote event delivery through a durable outbox and explicit
runtime.event.ack; receivers deduplicate byeventId. - Canonical workspace allowlists that reject path traversal and symlink escape.
- A local permission ceiling: remote callers can request less authority, never more authority than the machine owner configured.
- Structured agent transport rather than scraping a human terminal UI.
- Node.js 22.13 or newer and pnpm 10.
- At least one supported coding-agent CLI installed and already authenticated on
the local machine:
codex,claude, orkimi.
The daemon never accepts provider API keys in a task. Each adapter uses the agent's existing local login and credential store.
git clone https://github.com/Coiggahou2002/byoa-runtime.git
cd byoa-runtime
pnpm install --frozen-lockfile
pnpm build
node dist/cli.js doctordoctor reports availability and adapter versions without printing provider
credentials.
Set the directories that remote or local requests may use, then invoke an agent:
export BYOA_ALLOWED_ROOTS=/absolute/path/to/workspaces
node dist/cli.js run \
--agent codex \
--cwd /absolute/path/to/workspaces/project \
--permission approve-reads \
--prompt "Inspect this repository and propose a test plan"Replace codex with claude or kimi. --session <name> requests a persistent
agent session; without it, the turn is one-shot.
cp .env.example .env
set -a; source .env; set +a
node dist/cli.js serveThe default listener is 127.0.0.1:43120. Binding to a non-loopback address is
rejected unless BYOA_RUNTIME_TOKEN contains a bearer token of at least 24
characters. For a remote team service, prefer BYOA_CONTROL_PLANE_URL=wss://...
plus a device-scoped BYOA_DEVICE_TOKEN; the daemon initiates that connection.
Local HTTP endpoints:
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/health |
Runtime identity and status |
GET |
/v1/agents |
Probe supported local agents |
POST |
/v1/tasks |
Submit an idempotent task |
GET |
/v1/tasks/:taskId |
Read durable task state |
GET |
/v1/tasks/:taskId/events |
Read persisted events |
GET |
/v1/tasks/:taskId/events/stream |
Stream history plus live SSE |
POST |
/v1/tasks/:taskId/cancel |
Cancel queued or running work |
When BYOA_RUNTIME_TOKEN is configured, send it as
Authorization: Bearer <token> on every local HTTP request.
| Variable | Default | Meaning |
|---|---|---|
BYOA_RUNTIME_HOST |
127.0.0.1 |
Local HTTP bind host |
BYOA_RUNTIME_PORT |
43120 |
Local HTTP port |
BYOA_STATE_DIR |
~/.byoa-runtime |
SQLite, machine identity, ACP state |
BYOA_ALLOWED_ROOTS |
current directory | Comma-separated workspace roots |
BYOA_ALLOWED_AGENTS |
all three | Comma-separated agent allowlist |
BYOA_MAX_PERMISSION_MODE |
approve-reads |
Local authority ceiling |
BYOA_MAX_CONCURRENCY |
4 |
Simultaneous turns, maximum 64 |
BYOA_MAX_TURN_MS |
1800000 |
Local maximum task duration |
BYOA_LEASE_MS |
60000 |
Attempt lease duration |
BYOA_RUNTIME_TOKEN |
unset | Local HTTP bearer token |
BYOA_CONTROL_PLANE_URL |
unset | Outbound ws:// or wss:// URL |
BYOA_DEVICE_TOKEN |
unset | Control-plane device credential |
Task submission is idempotent on (controlPlaneId, idempotencyKey). Each run has
a distinct attemptId and increasing fencingToken, so an old process cannot
commit events or a terminal state after recovery creates a newer attempt.
Remote events are delivered at least once. The control plane must persist and
deduplicate each eventId, then send runtime.event.ack. Events remain in local
history after acknowledgement; the acknowledgement only removes them from the
outbound retry set.
See the architecture decision, wire protocol, and security model.
pnpm install --frozen-lockfile
pnpm check
pnpm buildReal-agent tests are separate because they spend model quota and use local authenticated sessions:
BYOA_E2E_AGENTS=codex,kimi,claude pnpm test:e2eEach test creates an isolated workspace marker, asks the real agent to read it through the daemon, verifies the exact model response, and verifies that a tool event crossed the normalized protocol boundary.
See CONTRIBUTING.md for development expectations. Please report vulnerabilities through the process in SECURITY.md, not a public issue.
BYOA Runtime's source is Apache-2.0. Runtime adapters and coding-agent SDKs keep their own licenses and terms; see THIRD_PARTY_NOTICES.md.