# AgentOS [简体中文](README_CN.md) AgentOS is a low-level, Linux-only operating-system agent written in Rust. It combines a bounded tool-calling loop with native Linux identities, read-only system inspection, durable audit state, Btrfs-backed filesystem history, and multiple inference backends—including an in-progress pure-Rust path for a CALCULET NPU. > **Development status:** the remote OpenAI-compatible mock path and explicit > subprocess/fake test adapters are implemented. Locally deployed model services > use Unix domain sockets, never localhost or TCP. The Rust Candle/CALRT host > pipeline can parse and validate the captured Qwen3 deployment, but CALRT > hardware job submission is not implemented yet. `npu_candle` therefore fails > closed and is not production-ready. ## Design AgentOS is not a container sandbox or a kernel fork. Its isolation boundary is the Linux process identity: - every active `AgentId` is stably bound to an owner UID and a non-root agent UID/GID; - the runtime verifies the process effective UID/GID before every run; - UID 0 or GID 0 agents are rejected; - `no_new_privs` is enabled before model/tool execution; - the model sees an explicit tool allowlist, never a raw root shell; - system mutation is intentionally unavailable until a typed, authenticated broker is implemented. The current execution path is: ```text agentos CLI -> runtime + Linux principal -> budgeted agent loop -> ChatBackend (remote OpenAI-compatible / UDS NPU / in-process Candle) -> strict ToolRegistry (read-only Linux tools) -> SQLite audit log filesystem state -> WorldlineStore -> Btrfs snapshots or copy fallback NPU host path -> Candle/Qwen3 -> CALRT -> PCIe driver ABI local model IPC -> Unix domain socket -> OpenAI-compatible HTTP payload ``` ## What works today - Provider-neutral `agentos.chat.v1` messages, tools, responses, usage, and backend interface. - Remote OpenAI-compatible non-streaming Chat Completions and Responses APIs over `ntex`, with bounded responses, timeouts, retries, and verified TLS when HTTPS is selected. - OpenAI-compatible HTTP payloads over an AF_UNIX transport for the local legacy llama-server, without a localhost/TCP hop. - A JSON stdin/stdout subprocess adapter retained for explicit tests and custom bridges; it is not the transport for a persistent local model service. - Bounded agent iterations, tool calls, elapsed time, total tokens, parallel read-only calls, duplicate call-ID checks, and no-progress/cycle detection. - Strict JSON tool schemas, allowlists, argument/output limits, deadlines, and hashed audit records. - Read-only Linux, package, systemd, journal, and CALCULET NPU inspection. - SQLite WAL state, FTS5 memory primitives, immutable principal bindings, and append-only agent/tool audit events. - Btrfs subvolume/snapshot worldlines with branch, diff, commit, log, non-destructive rollback, stale-branch protection, and checkout recovery. - Rust representations of CALCULET driver 0.9.0 / ABI 1.0.0, BAR and DMA access, Calbin 0.7.6 parsing, memory allocation, tensors, and command encoding. - A Candle-based Qwen3 host runner with chat templates, tool-call parsing, sampling, prefill/decode contracts, BF16/F32 logits, and vendor tiled-logit decoding. ## Workspace `agentos-cli` is the only binary crate; it produces two binaries. Every other workspace member is a library. | Crate | Type | Responsibility | | --- | --- | --- | | `agentos-cli` | binary | `agentos` CLI and `agentos-npu-bridge` | | `agentos-runtime` | library | configuration and composition root | | `agentos-agent` | library | bounded agent loop and audit emission | | `agentos-protocol` | library | provider-neutral chat/tool protocol | | `agentos-inference` | library | ntex, remote, subprocess, and test backends | | `agentos-tools` | library | tool policy, schema validation, approvals, Linux tools | | `agentos-core` | library | identities, IDs, events, and shared state types | | `agentos-kernel` | library | rustix-backed Linux and Btrfs boundary | | `agentos-memory` | library | SQLite memory, audit, and principal state | | `agentos-worldline` | library | filesystem branch/commit/rollback history | | `agentos-npu` | library | NPU discovery, legacy bridge, Candle assembly | | `agentos-candle` | library | Qwen3 host inference and CALRT tensor adapter | | `calculet-pcie-abi` | library | captured 64-bit Linux ioctl ABI | | `calculet-pcie` | library | safe PCIe device operations | | `calculet-calrt` | library | Calbin/runtime/command/tensor implementation | ## Requirements - 64-bit Linux. AgentOS itself is Linux-only, and the captured CALCULET ABI has only been verified on 64-bit Linux. - A current Rust toolchain with Rust 2024 edition support. - A C toolchain, `pkg-config`, and OpenSSL development files. SQLite is built from the bundled source. - Btrfs is recommended for kernel-enforced read-only commit snapshots, but is not required for development. On Debian/Ubuntu, the native build dependencies are typically: ```bash sudo apt install build-essential pkg-config libssl-dev ``` Build both binaries and all libraries: ```bash cargo build --workspace ``` ## Quick start without NPU hardware First inspect the host and backend configuration: ```bash cargo run -p agentos-cli --bin agentos -- \ --state-dir target/agentos-state --json doctor ``` Run a deterministic smoke test of the model/tool plumbing. This built-in fake requests the real read-only `system_inspect` tool, but it is not the remote mock used to substitute for unavailable NPU hardware: ```bash cargo run -p agentos-cli --bin agentos -- \ --state-dir target/agentos-state --fake-model --json \ agent once "Inspect this Linux system" ``` Do not run the agent as root. By default, its principal uses the current real UID as owner and the current effective UID/GID as the agent identity. ## Remote OpenAI-compatible mock inference Hardware-independent mock testing uses a remote OpenAI-compatible model. AgentOS supports either `/chat/completions` or `/responses` under a configured API base URL. Both HTTP and HTTPS remote URLs are accepted; HTTPS should be used whenever credentials or untrusted networks are involved. Localhost and loopback model URLs are rejected because local model services must use UDS. ```bash export AGENTOS_MODEL_BACKEND=openai_compatible export AGENTOS_OPENAI_COMPATIBLE_API_KEY='...' export AGENTOS_OPENAI_COMPATIBLE_BASE_URL='https://api.openai.com/v1' export AGENTOS_OPENAI_COMPATIBLE_MODEL='your-model' export AGENTOS_OPENAI_COMPATIBLE_API='responses' # or chat_completions cargo run -p agentos-cli --bin agentos -- \ --state-dir target/agentos-state \ agent once "Summarize the current system state" ``` `OPENAI_API_KEY` is accepted as a fallback. A non-empty credential is currently required by the remote adapter. Streaming is not implemented. ## Local model transport A persistent model on the same Linux host must expose a filesystem Unix domain socket. Do not bind it to localhost, a loopback address, or another TCP address. The socket path and its owner/group/mode are part of the OS security boundary. The legacy llama-server already supports this mode when `--host` ends in `.sock`. AgentOS carries the familiar OpenAI-compatible HTTP request format over AF_UNIX, so this is HTTP message framing over UDS—not HTTP over localhost. The pure-Rust Candle backend runs in-process and therefore needs no IPC socket. ## Read-only tools | Tool | Availability | Operation | | --- | --- | --- | | `system_inspect` | always | kernel, uptime, load, memory, root filesystem, OS release | | `npu_inspect` | always | CALCULET device nodes, module/sysfs/proc monitor, CALRT library | | `package_query` | always | exact package lookup via dpkg, rpm, or pacman | | `service_inspect` | configured | bounded `systemctl show` for an allowlisted service | | `journal_read` | configured | bounded journal read for an allowlisted service | Enable service tools with an exact comma-separated allowlist: ```bash export AGENTOS_SERVICE_INSPECT_ALLOWLIST='agentos.service,agentos-npud.service' ``` There are currently no mutation tools. The approval ledger in `agentos-tools` is a contract primitive, not a complete privilege broker. ## Filesystem worldlines Worldlines provide Git-like filesystem history without patching the kernel. On Btrfs, current/branch trees are writable snapshots and commit trees are read-only snapshots. Other filesystems use a copy fallback; that fallback does not provide kernel-enforced immutability. ```bash AGENTOS=(cargo run -q -p agentos-cli --bin agentos -- \ --state-dir target/agentos-state --json worldline) "${AGENTOS[@]}" init "${AGENTOS[@]}" branch "${AGENTOS[@]}" status "${AGENTOS[@]}" log --limit 20 ``` `branch` returns a worldline ID and path. Modify that branch tree, then use: ```bash "${AGENTOS[@]}" diff "${AGENTOS[@]}" commit --message "describe the change" "${AGENTOS[@]}" rollback --message "revert to known state" "${AGENTOS[@]}" discard ``` Rollback creates a new commit and retains history. Worldline operations are currently explicit CLI operations; agent runs do not automatically create or commit a branch. ## NPU paths ### Legacy llama-server bridge The legacy `npu` backend executes `agentos-npu-bridge`, which connects only to a filesystem Unix domain socket and sends `/v1/chat/completions` over that socket. It additionally requires a ready CALCULET device, driver sysfs state, and vendor CALRT shared library. ```bash export AGENTOS_MODEL_BACKEND=npu export AGENTOS_NPU_BRIDGE_COMMAND='agentos-npu-bridge' export AGENTOS_NPU_SERVER_SOCKET='/run/agentos/npu.sock' export AGENTOS_NPU_SERVER_MODEL='agentos-npu' # Optional when CALRT is not in a probed system location: export AGENTOS_CALRT_LIBRARY='/opt/calculet/lib/libcalrt-linux-x86_64.so' ``` Start the captured llama-server with the same socket path, for example `--host /run/agentos/npu.sock`, and restrict access using the socket directory and socket ownership/mode. No TCP listener is required. ### Pure-Rust Candle/CALRT path The `npu_candle` path replaces the modified llama.cpp host code with Rust: ```bash export AGENTOS_MODEL_BACKEND=npu_candle export AGENTOS_NPU_CALBIN='/path/to/calbin-directory' export AGENTOS_NPU_TOKENIZER='/path/to/tokenizer.json' export AGENTOS_NPU_DEVICE_INDEX=0 ``` `doctor` can parse these files and report the model plan without opening the device. For the captured Qwen3 deployment, the host validates a 40,960-token context, 151,936 logits, a 151,669-token vocabulary, and masks 267 padded logit IDs. This backend is deliberately not ready: `calculet-calrt` can deploy parameters and transfer tensors, but `ConfiguredRuntime::submit()` still lacks CCU relocation, job launch/completion, and device KV-cache reset. No real NPU result has been validated on the current development machine. ## Configuration | Variable | Default | Meaning | | --- | --- | --- | | `AGENTOS_STATE_DIR` | `$XDG_DATA_HOME/agentos` or `~/.local/share/agentos` | SQLite and worldline root | | `AGENTOS_MODEL_BACKEND` | `auto` | `auto`, `openai_compatible`, `npu`, `npu_candle`, `subprocess`, `fake` | | `AGENTOS_AGENT_ID` | `default-agent` | stable logical agent ID | | `AGENTOS_OWNER_UID` | real UID | owning Linux UID | | `AGENTOS_AGENT_UID` | effective UID | required execution UID | | `AGENTOS_AGENT_GID` | effective GID | required execution GID | | `AGENTOS_OPENAI_COMPATIBLE_API_KEY` | `OPENAI_API_KEY` | remote bearer credential | | `AGENTOS_OPENAI_COMPATIBLE_BASE_URL` | `https://api.openai.com/v1` | remote compatible API root; no localhost/loopback | | `AGENTOS_OPENAI_COMPATIBLE_MODEL` | empty | provider model name | | `AGENTOS_OPENAI_COMPATIBLE_API` | `chat_completions` | `chat_completions` or `responses` | | `AGENTOS_OPENAI_COMPATIBLE_MAX_RETRIES` | `2` | bounded HTTP retries | | `AGENTOS_MODEL_COMMAND` | empty | explicit subprocess test/bridge command | | `AGENTOS_MODEL_TIMEOUT_S` | `240` | model/bridge timeout | | `AGENTOS_NPU_BRIDGE_COMMAND` | empty | legacy NPU bridge command | | `AGENTOS_NPU_SERVER_SOCKET` | `/run/agentos/npu.sock` | legacy llama-server Unix socket | | `AGENTOS_NPU_SERVER_MODEL` | `agentos-npu` | legacy llama-server model name | | `AGENTOS_NPU_SERVER_TIMEOUT_S` | `240` | legacy llama-server UDS HTTP timeout | | `AGENTOS_NPU_CALBIN` | empty | pure-Rust Calbin directory | | `AGENTOS_NPU_TOKENIZER` | empty | pure-Rust tokenizer JSON | | `AGENTOS_NPU_DEVICE_INDEX` | `0` | `/dev/calculetN` index | | `AGENTOS_CALRT_LIBRARY` | probed | vendor CALRT shared library override | | `AGENTOS_SERVICE_INSPECT_ALLOWLIST` | empty | enabled systemd service names | | `AGENTOS_TOOL_OUTPUT_LIMIT_BYTES` | `65536` | per-tool serialized output limit | | `AGENTOS_TOOL_ARGUMENT_LIMIT_BYTES` | `65536` | per-call argument limit | | `AGENTOS_AGENT_MAX_ITERATIONS` | `8` | model/tool loop turns | | `AGENTOS_AGENT_MAX_TOOL_CALLS` | `16` | total tool calls per run | | `AGENTOS_AGENT_MAX_ELAPSED_S` | `120` | total run deadline | | `AGENTOS_AGENT_MAX_OUTPUT_TOKENS` | `2048` | model output budget per turn | | `AGENTOS_AGENT_MAX_TOTAL_TOKENS` | `65536` | cumulative token budget | | `AGENTOS_AGENT_MAX_SAFE_WORKERS` | `4` | parallel safe-tool workers | In `auto` mode, AgentOS selects the UDS-backed legacy NPU and then the remote OpenAI-compatible backend. Subprocess and fake are explicit test adapters. The incomplete Candle backend is not selected automatically. ## State layout ```text AGENTOS_STATE_DIR/ agentos.sqlite3 # principals, audit events, memory, FTS index worldline/ current/ # active filesystem tree branches/ # writable candidate trees commits/ # commit trees metadata/ # commit and branch records refs/ # HEAD references replaced/ # recoverable previous checkouts ``` ## Development ```bash cargo fmt --all --check cargo test --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings ``` Some NPU parser tests use the local, gitignored `npu_features/snapshot_20260801` capture. Those tests validate host-side parsing only. They are not hardware tests, and a clean clone may not contain the fixture. Project-owned low-level Linux calls use `rustix`; AgentOS does not directly add `libc` syscall wrappers. This is not a claim that the final `std`/OpenSSL binary has no libc ABI dependency. ## Known gaps - No long-running AgentOS control daemon or privilege broker yet; the local llama-server model transport already uses UDS. - No mutation tools or complete privilege-approval path. - No streaming remote inference. - No completed pure-Rust NPU job submission or physical-board validation. - The copy worldline backend lacks Btrfs's kernel-enforced read-only commits. - Memory/recall primitives exist as a library but are not exposed as agent tools or CLI commands yet. ## License notes AgentOS crates declare Apache-2.0. The captured CALCULET PCIe ABI and device wrapper crates declare GPL-2.0-only, while `calculet-calrt` retains its vendor license file. Check the individual crate manifests before redistribution.