Early development · milestone 2
The assistant that stays.
ka agent is a resident assistant for the Ka coding engine: one always-on daemon per person that keeps working across sessions and channels. Durable memory, explicit approvals, Telegram. All model reasoning and tool execution stay in Ka engines that ka agent starts, watches, and stops.
MIT license · Rust · Linux · built on the Ka engine
kick off the release-notes draft from the commits since v0.2
approval · bash
expires in 14:52
cargo test --workspace
Why resident
Sessions end. Work doesn't.
A coding agent that lives for one terminal session forgets everything the moment you close it. Nothing remembers you across projects, answers from your phone, runs at 07:00, or waits for your approval while you are away.
ka agent is the missing layer: a separate, optional, long-running process owned by one person. It provides channels (Telegram first), durable identity, memory and history, tasks and approvals. The problem it solves is continuity with control: an assistant that persists and acts across time and channels, whose memory, permissions and external actions you can inspect, edit and veto.
The engine never grows a daemon. ka stays a small, session-scoped coding tool; ka agent starts, watches and stops ka engines on demand and keeps nothing of theirs. Two products, one boundary, no lock-in either way.
The naming
Egyptian mythology, borrowed honestly.
- ka
Ka the vital essence
The turn engine: models, tools, permissions, strands. Session-scoped; lives and dies with a terminal.
- ba
Ba the mobile personality
Identity, memory, channels, presence. The part of the agent that moves between your phone and your desk.
- akh
Akh the effective spirit
A running agent: Ba bound to live Ka engines, acting in the world under your approvals.
What it does
Continuity, with control.
Every claim below is behavior you can check in the repository today: durable queues, expiring approvals, audited decisions, supervised workers.
Resident, not restarted
One daemon per operator, always on. Inbound messages land in a durable SQLite queue and drain one turn at a time; after a crash or reboot, the next message resumes the session on its recorded strand. Workers respawn with backoff and a crash-loop breaker that degrades instead of thrashing.
Telegram built in
Long polling with a persisted offset (at-least-once, deduped), numeric-id allowlist for private chats, local commands, typing indicator with progress edits, and approval cards with inline keyboards.
Approvals fail closed
Every engine permission ask becomes a card with a TTL. Unanswered means denied: silence can never authorize. Decisions and expiries land in an append-only audit chain.
Budgets by default
Daily USD caps across sessions, enforced through the engine's spend guard; a token cap binds even for unpriced models. Spend is reported per turn.
Local-first and strict
State in SQLite, memory as plain Markdown, secrets in env or 0600 files, strict TOML config where unknown keys are errors. Nothing leaves the machine except model API calls and the channels you configure.
The boundary
One port to the engine
ka-agent-port is the only crate that knows Ka types. Swapping the boundary implementation is a one-crate change; the contract is tested on every Ka upgrade.
Forwarded
prompt · answer · abort · set_mode · set_model · set_name · compact
Never reachable from a channel
shell · set_feature · set_sandbox · save_api_key · save_settings · "always" answers
Install
Build it from source.
$ git clone https://github.com/jaltez/ka-agent.git && cd ka-agent
$ sed -i 's|file:///home/javier/projects/ka-harness|https://github.com/jaltez/ka-harness|g' \
Cargo.toml crates/*/Cargo.toml apps/*/Cargo.toml
$ cargo install --path apps/ka-agent
$ ka-agent doctor && ka-agent run
Pre-release: not on crates.io yet, and the Ka crates are pinned to unreleased 0.3.0 revisions · the sed rewrites the local mirror pin to the public repository, same as CI · full installation guide
Under the hood
A resident layer, not a bigger engine.
One-way layering: channels talk to the runtime, the runtime talks to engines only through the port, and ka itself stays untouched.
apps/ka-agent
the binary · run, status, chat, doctor, __worker
ka-agent-core
domain types & state machines · no I/O
ka-agent-port
KaPort + worker protocol · the only crate that touches ka-*
ka-agent-store
SQLite schema, migrations, audit chain
ka-agent-runtime
sessions, queue, approvals, budgets, supervisor
ka-agent-channels
Telegram Bot API channel · secret store
Telegram / admin CLI → daemon → KaPort → ka engine
· a dependency gate in CI keeps every ka-* import inside the port · read the architecture →
Status
Incipient, on purpose.
One user, one channel, one workspace first; everything expands only behind exit criteria. This is the whole honest picture today.
Working today
- Session manager with durable queue and single-flight submission
- Approvals with TTL, deny-on-expiry and an audit chain
- Worker supervisor: backoff, crash-loop breaker, kill escalation
- Telegram channel: long polling, allowlist, commands, approval cards
- Admin unix socket; run / status / chat / doctor CLI
- 87 tests green; the Telegram flow verified end to end against a fake Bot API
Next milestones
- Memory: compiled MEMORY.md with a candidates review step
- Episodic history with /history search
- Plugins and connectors through an MCP bridge
- Scheduler for reminders and scheduled jobs
- A local web UI for approvals, memory and history