I've been running a self-hosted Aider instance for a few weeks now, mostly happy with its git integration. But the more I watched it work, the more a specific pattern started to itch: the agent writes files directly to my working directory, and while it *usually* uses git, there's nothing enforcing that all writes are part of a commit cycle. A stray bug, a malformed instruction, or a dependency hallucination could lead to uncontrolled file generation, filling a disk or clobbering sensitive configs.
Instead of wrapping the entire agent in a heavy VM, I built a small, focused daemon that sits between the agent and the filesystem. Its only job is to intercept, rate-limit, and log every `write` or `rename` syscall targeting the workspace. It's a userspace solution, leveraging `ptrace` to be runtime-agnostic—it works with Python, Node, or any binary the agent might spawn.
The core idea is a simple allowlist with a token-bucket rate limiter. You define a directory (like `/workspace`) and a maximum number of writes per minute. The daemon permits all writes within that directory but enforces the limit. Crucially, it logs every attempt—successful or throttled—with a hash of the content. This gives you an immutable audit trail of what the agent tried to create and when.
Here's a snippet of the core policy configuration:
```yaml
workspace_path: "/home/agent/workspace"
max_writes_per_minute: 50
log_file: "/var/log/agent_writes.log"
audit_mode: false # if true, logs but does not throttle
```
When `audit_mode` is false and the agent exceeds 50 writes in a minute, subsequent writes are delayed (not rejected) to smooth out bursts. This prevents a runaway script from causing a denial-of-service against its own workspace, while still allowing legitimate high-activity operations to complete, just more slowly.
The log output is structured for easy parsing:
`2024-05-15T14:23:17Z | ALLOWED | /home/agent/workspace/src/main.rs | sha256:a1b2c3... | 2048 bytes`
This approach complements broader sandboxing (like gVisor or a WASM runtime) by adding a fine-grained, observable control layer at the filesystem boundary. It's a step towards treating the agent not as a trusted user, but as a service with explicit, measurable resource constraints. I'm considering adding hooks to automatically commit allowed writes to git, closing the loop on that original concern. What other agent actions would benefit from this kind of transparent interposition?
Sandboxed from the kernel up.