Skip to content

hdresearch/zagent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

114 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zagent

A minimal SWE agent written entirely in Zig. Interactive by default.

Built-in knowledge of ziggit for git. No external dependencies — everything is pure Zig.

Quick start

# Build
zig build

# Interactive mode (default)
zagent

# Single task
zagent "fix the bug in main.py"
zagent fix the bug in main.py          # unquoted works too

Usage

zagent                              Interactive mode (default)
zagent "task description"            Run task and exit
zagent fix the bug in main.py        Unquoted args joined as task

Options

-m, --model NAME        Model name (default: auto from env)
--api-base URL          API base URL
--api-key KEY           API key
--cwd PATH              Working directory for commands
--step-limit N          Max steps per task (0 = unlimited)
--cost-limit F          Max cost in USD (default: 3.0)
--temperature F         Sampling temperature (default: 0.0)
--cache MODE            Prompt cache mode: none, anthropic
--context-limit N       Override context window size (tokens, for testing)
--no-start              Skip `ziggit start`
--no-progress           Skip `ziggit progress`
-v, --verbose           Show full command output

Environment variables

Variable Description
ANTHROPIC_API_KEY API key for Claude models
OPENAI_API_KEY API key for OpenAI models
ZAGENT_MODEL Default model name
ZAGENT_API_BASE Default API base URL
VERS_API_KEY Vers platform API key (enables VM tools)
VERS_URL Vers API base URL (default: https://api.vers.sh)

What's built in

Git (ziggit)

The agent uses ziggit for version control. Both zagent and ziggit binaries are built together:

zig build    # → zig-out/bin/zagent, zig-out/bin/ziggit

The workflow:

  • ziggit start runs before each task (sync with upstream)
  • The LLM uses ziggit progress "description" to save checkpoints mid-task
  • ziggit progress runs after completion (commit + push)

Raw git commands are blocked — the agent is instructed to use ziggit exclusively (and autocorrected if it doesn't).

Autocorrect

Commands are silently fixed instead of rejected:

Typed Corrected to
cmd & / nohup cmd & __bg cmd
git status ziggit status
pip install X uv add X
python script.py python3 script.py
sl, gti, grpe, cta, … ls, ziggit, grep, cat, …

Post-execution fixes: command not found retries with typo correction, Permission denied on scripts retries with chmod +x.

Output compression

Command output is compressed before feeding back to the model to save tokens:

  • Test runners: show only failures + summary line (~90% savings)
  • Build tools: errors/warnings only (~80% savings)
  • Package managers: strip progress bars and noise
  • grep/rg: cap results, group by file
  • cat/source: strip comments (language-aware)
  • env/printenv: mask secrets (API keys, tokens, passwords)
  • docker/kubectl: compact listings, dedup logs
  • tree/find/ls: filter noise dirs, cap output
  • diff: compact unified diff
  • General: collapse blanks, dedup repeated lines, cap at ~6K chars

Vers VM integration

When VERS_API_KEY is set, zagent gains native tools for managing Vers Firecracker VMs — no external CLI needed:

Tool Description
vers_vm_create Create a new VM
vers_vm_delete Delete a VM
vers_vm_list List all VMs
vers_vm_use Set active VM — routes bash through SSH
vers_vm_branch Clone a VM (like git branch for machines)
vers_vm_commit Snapshot VM state
vers_vm_restore Restore from snapshot
vers_vm_exec One-off command on a VM

After vers_vm_use, all bash tool calls execute on the VM via SSH (using the Vers SSH-over-TLS transport). Call vers_vm_use with "local" to switch back.

Repo management tools for organizing commits:

Tool Description
vers_repo_create Create a named repository
vers_repo_list List all repositories
vers_repo_delete Delete a repository
vers_repo_tag Create/list tags in a repo

Code cannon (parallel agent orchestration)

A Code Cannon is an RLM (Reinforcement Learning from Memory) orchestrator. Use as a subcommand or include "code cannon" in your prompt:

zagent code-cannon "build a chess website with React frontend and Python backend"
zagent "code cannon: fix the flaky test suite"   # phrase detection also works

zagent will:

  1. Decompose the task into independent sub-tasks
  2. Spawn parallel agents on Vers VMs from the golden snapshot
  3. Agents work independently, each running:
    ziggit start → pi "sub-task" → ziggit progress → repeat
    
  4. Collect reports — what worked, what failed, what remains
  5. Plan the next iteration using full history (the "infinite context")
  6. Repeat until done or budget exhausted

Key property: memory. Each iteration builds on the last. The orchestrator knows what was tried, what worked, what failed, and why.

Agents use prefix conventions for organization:

  • chess-frontend-ui — React component agent
  • chess-frontend-state — State management agent
  • chess-backend-api — API server agent
  • chess-backend-engine — Chess engine agent

Each agent gets a distinct git author name matching its prefix, pushing to the same repo. ziggit start handles merging across agents.

Code pirate (strategic review loop)

A Code Pirate is a stateless strategic reviewer that fires Code Cannons. It maintains a living manifest (checklist) tracking what's done, failing, and missing — then fires cannons at the highest-impact gaps:

zagent code-pirate "take sterling to 100% completion"
zagent code-pirate --manifest ~/.zagent/pirate-sterling.md "fix remaining items"

zagent will:

  1. Read the manifest (~/.zagent/pirate-<slug>.md) — its only memory
  2. Review the actual project with fresh eyes (clone/pull, build, test)
  3. Update the manifest with findings (PASS/FAIL with evidence)
  4. Fire code cannons at the most impactful gaps
  5. Monitor cannons, record results, loop back to 1

Key property: stateless review. Fresh context each round means no accumulated assumptions. The manifest IS the memory — a human-readable, human-editable living document outside the repo.

The manifest lives at ~/.zagent/ — never in the repo, never visible to subagents. A human can view/edit it between rounds to steer priorities.

Items can only be marked PASS with verification evidence (exact command + output). "I looked at the code and it seems right" is not sufficient.

Works in interactive mode too — type "code pirate" in any prompt to activate.

Context management

The agent automatically manages context window usage:

  • 70%: truncates old tool observations (age-based — older = more aggressive)
  • 80%: summarizes conversation history and rebuilds with summary + recent turns
  • Overflow: emergency drop to system + last N messages
  • Loop detection: nudges the agent when the same action repeats 3+ times

Provider auto-detection

Model contains Protocol API base
claude or anthropic Anthropic native api.anthropic.com
anything else OpenAI-compatible api.openai.com

Prompt caching auto-enabled for Claude models, with adaptive cache breakpoint advancement — instead of writing a new cache entry every API call (paying 1.25× per token each time), the conversation breakpoint only advances every K≈4–15 calls based on an adaptive formula from optimal caching theory. The system prompt is always cached. This typically reduces cache write costs by 60–80% while maintaining high cache read rates.

Platform abstraction (WASM support)

zagent has a platform abstraction layer (src/platform.zig) that enables it to run in WebAssembly with a virtual filesystem — e.g. for a browser demo where ziggit clones a repo into memory and zagent works on those files.

Operation Native WASM (freestanding)
Shell execution bash -c subprocess host_exec() JS callback
HTTP (API calls) curl subprocess host_http_post() JS callback
Filesystem std.fs host_read_file() / host_write_file() etc.
Stdout/stderr fd 1/2 host_write_stdout() / host_write_stderr()
Env vars getenv() host_get_env() JS callback

The JS host implements the env module with these extern functions, backed by an in-memory filesystem (e.g. ziggit's virtual git repo) and a shell interpreter.

Architecture

src/
├── main.zig          CLI, interactive REPL, ziggit lifecycle
├── agent.zig         Agent loop, context management, loop detection
├── model.zig         Dual LLM client (OpenAI + Anthropic native)
├── environment.zig   Bash execution, autocorrect, background processes
├── compress.zig      Output compression (10+ command categories)
├── platform.zig      Platform abstraction (native + WASM)
├── vers.zig          Vers VM API client (pure Zig, no CLI)
├── git.zig           ziggit CLI wrapper
├── config.zig        System prompt, observation templates
└── json.zig          JSON builder & extractor

Building

Requires Zig 0.15.2+:

zig build                        # debug
zig build -Doptimize=ReleaseFast # release
zig build test                   # run 96 tests

Acknowledgements

Agent-level token efficiency improvements — including adaptive cache breakpoint advancement and the optimal caching theory it's based on — were designed by Carter Tazio Schonwald. The adaptive formula (p* ∝ 1/√N) determines when to advance the conversation cache breakpoint, reducing cache write costs by 60–80% while maintaining high read rates across long sessions.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors