Agent Experience: Linux vs KruxOS¶
The same tasks, side by side. See how KruxOS's typed APIs eliminate the parsing, guessing, and retry loops that consume tokens on traditional Linux.
Reading a file¶
# Agent must construct shell command, parse text output, handle encoding
import subprocess
result = subprocess.run(
["cat", "/workspace/data.csv"],
capture_output=True, text=True
)
if result.returncode != 0:
# What went wrong? Parse stderr to guess
if "No such file" in result.stderr:
# Try to find the file
find_result = subprocess.run(
["find", "/workspace", "-name", "data.csv"],
capture_output=True, text=True
)
# Parse find output...
elif "Permission denied" in result.stderr:
# Can't tell why — is it a policy? A file permission? SELinux?
pass
else:
# Unknown error — retry? Give up?
pass
content = result.stdout # Hope it's the right encoding
result = await agent.capabilities.invoke(
"filesystem.read",
path="/workspace/data.csv"
)
if result.success:
content = result.data["content"]
size = result.data["size_bytes"]
modified = result.data["modified_at"]
else:
# Structured error with recovery suggestions
match result.error.type:
case "FileNotFound":
# Recovery: "Use filesystem.list to see available files"
pass
case "PermissionDenied":
# Recovery: "Use agent.policy to check path access"
pass
Token cost: ~200 tokens (KruxOS) vs ~500 tokens (Linux). The Linux agent spends tokens on output parsing, error guessing, and retry attempts.
Handling errors¶
# Agent runs a command that fails
result = subprocess.run(["python3", "train.py"], capture_output=True, text=True)
if result.returncode != 0:
# stderr is a wall of text — agent must parse it
stderr = result.stderr
# Is it a missing module? Wrong Python version? Syntax error?
# OOM? Permission issue? Agent has to pattern-match on raw text.
if "ModuleNotFoundError" in stderr:
# Try pip install? Which package? Parse the module name from the traceback
module = stderr.split("No module named '")[1].split("'")[0]
subprocess.run(["pip", "install", module])
# Retry... but was that the right package name?
elif "PermissionError" in stderr:
# Try sudo? That's blocked. Try chmod? What permissions?
pass
# ... more string parsing
try:
result = await agent.capabilities.invoke(
"process.run",
command="python3 train.py"
)
except CapabilityError as e:
# Structured error — no parsing needed
print(f"Error: {e.type}") # "ProcessFailed"
print(f"Exit code: {e.data['exit_code']}") # 1
print(f"Stderr: {e.data['stderr']}") # Full stderr preserved
for recovery in e.recovery:
print(f"Try: {recovery.action}")
# "retry" — "Retry the command"
# "check_dependencies" — "Verify required modules are installed"
Token cost: ~150 tokens (KruxOS) vs ~800 tokens (Linux). Error recovery on Linux burns tokens on pattern matching, wrong guesses, and retry loops.
Discovering available tools¶
# Agent doesn't know what it can do. Trial and error:
result = subprocess.run(["which", "git"], capture_output=True, text=True)
has_git = result.returncode == 0
result = subprocess.run(["which", "docker"], capture_output=True, text=True)
has_docker = result.returncode == 0
# Check version to guess available flags
result = subprocess.run(["git", "--version"], capture_output=True, text=True)
# Parse "git version 2.43.0" → is this new enough for sparse-checkout?
# Read man pages for usage — thousands of tokens
result = subprocess.run(["man", "git-log"], capture_output=True, text=True)
# 5000+ tokens of man page text...
# Discover everything available, with schemas
caps = await agent.capabilities.list()
# Returns: 86 capabilities with purpose, inputs, outputs
# Get details for one capability
cap = await agent.capabilities.describe("git.log")
print(cap.purpose) # "Returns the commit log..."
print(cap.when_to_use) # "Use git.log to see recent commits..."
for inp in cap.inputs:
print(f" {inp.name}: {inp.type}") # Typed parameters
Token cost: ~100 tokens (KruxOS) vs ~5000+ tokens (Linux). Man pages and --help output are massive. KruxOS provides exactly what the agent needs.
Working with secrets¶
import os
# Secret is in an environment variable — agent can see it
api_key = os.environ.get("OPENWEATHER_API_KEY")
# Agent now has the raw secret. It could:
# - Log it accidentally
# - Include it in an error report
# - Send it to another service
# - Store it in persistent state
response = requests.get(
f"https://api.openweathermap.org/data/2.5/weather?q=London&appid={api_key}"
)
# Agent never sees the secret — use-not-read model
result = await agent.capabilities.invoke(
"weather.current",
location="London"
)
# The capability implementation accessed the secret internally
# via the vault. The agent only gets the weather data back.
# Even if the agent tries to read the secret directly:
result = await agent.capabilities.invoke(
"secrets.use", name="OPENWEATHER_API_KEY"
)
# Returns: {"injected": true, "capability": "weather.current"}
# NOT the actual secret value
Security: On Linux, the agent has the raw secret. On KruxOS, secrets are injected into capability execution environments — the agent never sees them.
Multi-step workflow¶
# Search for files, read them, create a report — lots of text parsing
# Step 1: Find Python files
result = subprocess.run(
["find", "/workspace", "-name", "*.py", "-type", "f"],
capture_output=True, text=True
)
files = result.stdout.strip().split("\n")
# Hope there are no filenames with newlines...
# Step 2: Count lines in each file
total_lines = 0
for f in files:
result = subprocess.run(
["wc", "-l", f], capture_output=True, text=True
)
# Parse " 42 /workspace/main.py" — split on whitespace
count = int(result.stdout.strip().split()[0])
total_lines += count
# Step 3: Write report
report = f"Found {len(files)} Python files, {total_lines} lines total\n"
with open("/workspace/report.txt", "w") as fh:
fh.write(report)
# Step 1: Search for Python files
result = await agent.capabilities.invoke(
"filesystem.search",
directory="/workspace",
pattern="*.py"
)
files = result.data["matches"] # Structured list
# Step 2: Get file stats
total_lines = 0
for f in files:
stat = await agent.capabilities.invoke(
"filesystem.stat", path=f["path"]
)
total_lines += stat.data["line_count"]
# Step 3: Write report
report = f"Found {len(files)} Python files, {total_lines} lines total\n"
await agent.capabilities.invoke(
"filesystem.write",
path="/workspace/report.txt",
content=report
)
# Write is soft-deleted recoverable for 24 hours
Token cost: ~1,200 tokens (KruxOS) vs ~3,000 tokens (Linux). Every shell command requires text parsing and error checking that consumes tokens.
Sending email safely¶
import smtplib
from email.mime.text import MIMEText
# Direct SMTP — no safety net
msg = MIMEText("Quarterly report attached.")
msg["Subject"] = "Q1 Report"
msg["From"] = "[email protected]"
msg["To"] = "[email protected]" # Oops — sent to ALL staff
# Sent immediately. No undo. No approval. No buffer.
with smtplib.SMTP("smtp.gmail.com", 587) as server:
server.starttls()
server.login(os.environ["GMAIL_USER"], os.environ["GMAIL_PASS"])
server.send_message(msg) # Gone. Can't take it back.
result = await agent.capabilities.invoke(
"email.send",
to="[email protected]",
subject="Q1 Report",
body="Quarterly report attached."
)
# Not sent yet — buffered for 5 minutes
print(f"Will send at: {result.data['buffer_until']}")
print(f"Cancel with: proxy.cancel_write(write_id='{result.data['write_id']}')")
# Supervisor gets notified and can cancel
# Batch protection kicks in at 20 sends/hour
# Rollback point created automatically
# If it was a mistake:
await agent.capabilities.invoke(
"proxy.cancel_write",
write_id=result.data["write_id"]
)
# Email never sent. Crisis averted.
Safety: On Linux, sends are immediate and irrevocable. On KruxOS, every write to an external service is buffered, cancellable, batch-protected, and rollback-enabled.
Summary¶
| Dimension | Traditional Linux | KruxOS |
|---|---|---|
| Interface | Shell commands + text parsing | Typed APIs + structured responses |
| Error handling | Parse stderr text, guess the cause | Typed errors with recovery actions |
| Discovery | which, --help, man (thousands of tokens) |
Schema-aware capability listing |
| Secrets | Environment variables (visible to agent) | Use-not-read vault (never exposed) |
| External services | Direct API access (immediate, irrevocable) | Buffered, cancellable, rollback-enabled |
| Token efficiency | Baseline | ~60% fewer tokens |
| Task completion | ~65-85% | ~90-98% |
| Audit | Container logs (deletable) | Hash-chained, tamper-proof, queryable |
The difference is not about what agents can do — it's about how efficiently and safely they do it.