> nix-agent-tool-design

Applies the *nix Agent design philosophy to agent tool interfaces. Use when asked to design, review, or refactor how an AI agent exposes tools — especially when considering function-calling vs CLI approaches, tool interface reduction, output truncation/overflow, binary guards, stderr handling, or two-layer execution/presentation architecture. Trigger phrases: "design agent tools", "single run tool", "CLI for agents", "tool interface design", "agent tool architecture", "function calling vs CLI",

fetch
$curl "https://skillshub.wtf/Mind-Dragon/atoolix/nix-agent-tool-design?format=md"
SKILL.mdnix-agent-tool-design

*nix Agent Tool Design

A single run(command="...") tool with Unix-style commands outperforms a catalog of typed function calls.

Credit: This design was authored by the backend lead at Manus and is implemented in the open-source agent-clip runtime by @epiral. This skill packages that knowledge for use in OpenCode, OpenClaw, and Pinix.


Core Philosophy

Unix and LLMs made the same architectural decision 50 years apart: everything is text.

  • Unix: text streams, pipes, exit codes, --help, stderr
  • LLMs: tokens in, tokens out — they only understand and produce text

This convergence means the Unix terminal interface is the LLM's native tool interface. Don't invent a new one.


Principle 1: Single run Tool

Replace a catalog of typed function calls with one tool:

run(command="...")

All capabilities exposed as CLI subcommands. The LLM composes strings instead of switching between unrelated API schemas.

Why it works:

  • LLMs have seen billions of shell commands in training data — they already know CLI
  • Command selection = string composition in one namespace
  • Function selection = context-switching between N unrelated APIs
  • Reduces "which tool?" cognitive load; agent focuses on "what do I need?"

Example reduction:

# Function-calling (3 calls):
read_file(path="/var/log/app.log")
search_text(text=<file>, pattern="ERROR")
count_lines(text=<matches>)

# CLI (1 call):
run(command="cat /var/log/app.log | grep ERROR | wc -l")

Principle 2: Chain Parser (parseChain)

Support four Unix chain operators so a single tool call = a complete workflow:

OperatorBehavior
|Pipe: stdout of previous → stdin of next
&&And: next only if previous succeeded (exit 0)
||Or: next only if previous failed (exit ≠ 0)
;Seq: next regardless of result

Examples:

curl -sL $URL -o data.csv && cat data.csv | head 5    # download → inspect
cat access.log | grep "500" | sort | head 10           # read → filter → sort → top 10
cat config.yaml || echo "config not found, using defaults"  # try A, fall back to B

Principle 3: Progressive --help Discovery (3 levels)

Never stuff full documentation into the system prompt. Use progressive disclosure:

Level 0 — Tool description → command list (injected at conversation start)

Available commands:
  cat    — Read a text file. For images use 'see'. For binary use 'cat -b'.
  see    — View an image (auto-attaches to vision)
  ls     — List files in current topic
  write  — Write file. Usage: write <path> [content] or stdin
  grep   — Filter lines matching a pattern (supports -i, -v, -c)
  memory — Search or manage memory
  clip   — Operate external environments (sandboxes, services)

Level 1 — command with no args → usage string

run(command="memory")
→ [error] memory: usage: memory search|recent|store|facts|forget

Level 2 — command subcommand with missing args → specific parameters

run(command="memory search")
→ [error] memory: usage: memory search <query> [-t topic_id] [-k keyword]

Requirement: Every command and subcommand MUST have complete help output. A good help message means one-shot success. A missing one means a blind guess.


Principle 4: Error Messages as Navigation

Every error must contain: what went wrong + what to do instead.

# Traditional (useless to agents):
cat: binary file (standard output)

# Agent-optimized:
[error] cat: binary image file (182KB). Use: see photo.png
[error] unknown command: foo — Available: cat, ls, see, write, grep, memory, clip
[error] clip "sandbox" not found. Use 'clip list' to see available clips

Production lesson: Silent stderr caused 10 blind retries to find the right package manager. Always surface stderr on failure.

# WRONG:
if stdout != "": discard stderr

# RIGHT:
always attach stderr on failure:
output + "\n[stderr] " + stderr

Principle 5: Consistent Output Format

Append [exit:N | Xms] to every tool result:

file1.txt
file2.txt
dir1/
[exit:0 | 12ms]

Exit code semantics (LLMs already know these):

  • exit:0 — success
  • exit:1 — general error
  • exit:127 — command not found

Duration signals cost:

  • 12ms — cheap, call freely
  • 3.2s — moderate
  • 45s — expensive, use sparingly

Consistent format = agent internalizes pattern over the conversation. Inconsistency makes every call feel like the first.


Principle 6: Two-Layer Architecture (CRITICAL)

Raw command output ≠ what the LLM should receive. Two hard LLM constraints drive this:

  • Constraint A: Context window is finite and expensive
  • Constraint B: LLMs cannot process binary data (produces meaningless high-entropy tokens that degrade surrounding attention)
┌─────────────────────────────────────────────────┐
│  Layer 2: LLM Presentation Layer                │  ← Designed for LLM constraints
│  Binary guard | Truncation+overflow | Meta      │
├─────────────────────────────────────────────────┤
│  Layer 1: Unix Execution Layer                  │  ← Pure Unix semantics
│  Command routing | pipe | chain | exit code     │
└─────────────────────────────────────────────────┘

CRITICAL: Layer 1 must be raw, lossless, metadata-free. If you truncate in Layer 1, grep only searches the first 200 lines. If you add [exit:0] in Layer 1, it becomes grep data. Processing only happens in Layer 2.

Layer 2 Mechanisms

A. Binary Guard

Null byte detected → binary
UTF-8 validation failed → binary  
Control character ratio > 10% → binary

→ [error] binary image (182KB). Use: see photo.png
→ [error] binary file (1.2MB). Use: cat -b file.bin

B. Overflow Mode

Output > 200 lines or > 50KB?
  → Truncate to first 200 lines (rune-safe)
  → Write full output to /tmp/cmd-output/cmd-{n}.txt
  → Return:
    [first 200 lines]
    --- output truncated (5000 lines, 245.3KB) ---
    Full output: /tmp/cmd-output/cmd-3.txt
    Explore: cat /tmp/cmd-output/cmd-3.txt | grep <pattern>
             cat /tmp/cmd-output/cmd-3.txt | tail 100
    [exit:0 | 1.2s]

The agent already knows grep, head, tail — overflow mode turns large data into a familiar navigation problem.

C. Metadata Footer

[exit:0 | 1.2s]

Appended after the pipe chain completes. Never in Layer 1.

D. stderr Attachment

output + "\n[stderr] " + stderr

Always on failure. Never drop it when stdout is non-empty.


When NOT to Use CLI

Typed APIs may be better when:

  • Strongly-typed interactions — DB queries, GraphQL, schema validation required
  • High security — CLI string concatenation has injection risk; use typed params + sandbox isolation
  • Native multimodal — Pure audio/video binary stream processing

Safety boundaries are external (not iteration limits):

  • Sandbox isolation (e.g., BoxLite containers)
  • API spending caps
  • User cancellation with graceful shutdown

Production War Stories

StoryRoot CauseFixLesson
PNG caused 20 iterations of thrashingNo binary guard in Layer 2isBinary() + Use: see photo.pngReturn garbage = agent goes blind
10 blind retries to find package managerSilent stderr when stdout non-emptyAlways attach stderr on failurestderr is most needed when commands fail
5,000-line log overwhelmed contextNo overflow modeTruncate + write to /tmp + give explore commandsA map beats the entire territory

Implementation Reference

Original implementation by @epiral:

RepoDescription
epiral/agent-clipThe agent as a Pinix Clip — full Go implementation of these principles
epiral/pinixDecentralized runtime platform that hosts Clips (BoxLite micro-VMs, Edge Clips)
FileResponsibility
internal/tools.goCommand routing, single run entry point
internal/chain.goPipe/&&/||/; chain parser
internal/loop.goTwo-layer agentic loop
internal/fs.goBinary guard
internal/clip.gostderr handling
internal/browser.goVision auto-attach
internal/memory.goSemantic memory commands

┌ stats

installs/wk0
░░░░░░░░░░
first seenMar 18, 2026
└────────────

┌ repo

Mind-Dragon/atoolix
by Mind-Dragon
└────────────

┌ tags

└────────────