title: Cowboy Design tags: [index, overview, architecture] created: 2026-02-16 updated: 2026-02-24

Cowboy Design

Design documentation for cowboy, a Nix-native AI agent platform built as a Zellij WASM plugin.

Two-Library Architecture

The system is split into two publishable libraries:

  • cowboy -- the platform: Zellij WASM plugin (runtime), agent-bridge Python framework, agent-proxy (credential-injecting proxy), NixOS modules, home-manager config
  • agent-pkgs -- swappable bridge services (discord-service, email-service) that connect external platforms to cowboy via the bridge API

The agent name is configurable via cfg.name (default: "agent"). This flows through all service names, paths, and systemd units. A broker (the human operator, e.g. dylan) gets a launcher command installed in their home-manager config.

Architecture Overview

+-----------------------------------------------------------------+
|                         Zellij Session                          |
+-----------------------------------------------------------------+
|  +-----------------------------------------------------------+  |
|  |                   Cowboy Plugin (WASM)                     |  |
|  |  +-------------+  +-------------+  +-----------------+    |  |
|  |  |   UI/TUI    |  | Agent Loop  |  |  Tool Executor  |    |  |
|  |  |  (Render)   |  |   (Core)    |  |  (RunCommands)  |    |  |
|  |  +-------------+  +------+------+  +--------+--------+    |  |
|  |                          |                   |             |  |
|  |  +-------------+   +----v-----+      +------v------+     |  |
|  |  |  Provider   |   | Context  |      |   Filter    |     |  |
|  |  |  Traits     |   | Manager  |      |  Pipeline   |     |  |
|  |  |(Claude/GPT) |   |(Session/ |      |  (Compiled) |     |  |
|  |  |             |   | Compact) |      +-------------+     |  |
|  |  +------+------+   +----------+                           |  |
|  |         |                                                  |  |
|  |   +-----v-----------------------+                          |  |
|  |   | web_request() [WebAccess]   |                          |  |
|  |   | (native HTTP in WASM)       |                          |  |
|  |   +-----------------------------+                          |  |
|  +-----------------------------------------------------------+  |
+-----------------------------------------------------------------+
                             |
                      +------v------+
                      | Proxy Layer |  (agent-proxy, host namespace)
                      | Injects API |  (credential injection, method gating)
                      | credentials |
                      +------+------+
                             |
                      +------v------+
                      |  LLM API    |
                      |(Claude/GPT) |
                      +-------------+

Pub/Sub Layer (agent-bridge + agent-pkgs)

External Platforms      Bridge Services (broker namespace)    Cowboy (agent namespace)
  Discord  ------>  discord-ingest ---> Redis:discord:inbox ---> plugin polls
  Email    <------  email-outbox   <--- Redis:email:outbox  <--- plugin writes
                         |
                    agent-bridge (shared Python lib)
                    approval protocol via Redis hashes

Design Principles

  1. No /tmp/ -- Full observability through persistent storage
  2. Nix-native -- All configuration via NixOS/home-manager modules
  3. Space is cheap -- Log everything, compress later
  4. Tee-style I/O -- Never block on disk operations
  5. Compiled security -- Filters are Rust, not runtime-modifiable
  6. Topology-based isolation -- Network namespace + proxy, not iptables rules

Core Components (Implemented)

[[API Integration]]

Native HTTP via Zellij web_request() with provider abstraction (Claude, OpenAI, local LLM). Includes retry logic with exponential backoff and tool use parsing.

Status: Provider trait (LlmProvider) and ClaudeProvider implemented in pkgs/agent-harness/src/provider.rs. Wiring to main loop in progress (WP11).

[[Pub/Sub]]

Generalized message source abstraction. The harness polls external sources (Discord, email) via Redis Streams. MessageSource trait generates shell commands (WASI-compatible), SourceManager orchestrates polling, acknowledgment, and reply routing.

Status: Fully implemented. types.rs defines InboundMessage, SourceConfig, MessageSource trait. manager.rs implements SourceManager. redis.rs implements RedisStreamsSource.

[[Security]]

Three independent layers: network namespace (topology), credential-injecting proxy (method + auth), outbox approval gates (send policy). Agent never sees real API keys.

Status: nix/agents/network.nix creates namespace + veth pair. nix/agents/secrets-proxy.nix configures proxy with domain mappings and method-based egress. nix/agents/bridges.nix generates broker-owned systemd services.

[[Filters]]

Compiled Rust middleware pipeline: SecurityFilter, WorkspaceFilter, ApprovalFilter, AuditFilter. Agent cannot modify these at runtime.

Status: Nix module (nix/agents/filters.nix) defines options. Rust Filter trait and pipeline planned.

[[Nix Integration]]

Declarative configuration via NixOS modules:

  • services.agent.tools -- Tool definitions with JSON schemas, sandbox presets
  • services.agent.skills -- Skill compositions with system prompt injection
  • services.agent.filters -- Security configuration
  • services.agent.bridges -- Bridge service declarations (auto-generates pubsub + systemd)
  • Build-time manifest generation

Status: All Nix modules exist: tools.nix, skills.nix, filters.nix, sandbox.nix, pubsub.nix, bridges.nix, network.nix, secrets-proxy.nix, systemd.nix, user.nix, prompts.nix, pr-workflow.nix.

[[Approvals]]

Cross-service approval protocol. Outbox services hold messages for manual approval. Approval state in Redis hashes, notifications via configurable channel (default: Discord reactions).

Status: Nix options defined in pubsub.nix (approval submodule). Protocol documented. Discord reaction handling designed.

Core Components (Future)

[[Skills]]

Hierarchical skill system with cache-miss generation. Skills resolve transparently -- if missing, a sub-agent generates them. Workspace context.md files provide project-specific context.

[[Sub-Agents]]

Multi-pane orchestration via Zellij. File-based communication: prompt.md, conscious.md, response.md, lock.

[[Memory]]

zk-based zettelkasten for persistent knowledge. Daily journals, atomic facts, decisions/ADRs, wikilink-based retrieval.

[[Compaction]]

Context window management via Haiku sub-agent summarization at ~40k tokens.

[[Plan Mode]]

Read-only exploration before execution. Tool restrictions, produces plan + thinking artifacts, requires approval before execution.

[[Ralph Loop]]

Autonomous iteration pattern: PRD-driven decomposition, fresh context per iteration, quality gates, rollback on failure.

[[Self-Modification]]

Home-manager based capability evolution with heartbeat-protected switches and PR-gated dangerous changes.

Key Design Decisions

DecisionChoiceRationale
API transportNative web_request()No curl, no daemon overhead
Provider abstractionRust traitsType-safe, swappable implementations
SettingsNix onlyReproducible, validated at build time
Sub-agent commsFile-basedObservable, recoverable
FiltersCompiled RustSecurity boundary agent cannot modify
SandboxBubblewrapPer-tool, lightweight
Secrets isolationNetwork namespace + proxyTopology is the boundary, not rules
Message busRedis StreamsProven, XREADGROUP consumer groups
Bridge architectureShared lib + independent packagesagent-bridge provides boilerplate, services are separate derivations
Agent nameConfigurable cfg.nameSupports multiple agents per machine

Package Layout

cowboy/
  pkgs/agent-harness/     # Zellij WASM plugin (Rust)
  pkgs/agent-proxy/       # Credential-injecting HTTPS proxy
  pkgs/agent-bridge/      # Shared Python lib for bridge services
  nix/agents/             # NixOS + home-manager modules

agent-pkgs/
  pkgs/discord/           # Discord ingest + outbox service
  pkgs/email/             # Email outbox with DKIM signing

References