leather

releases | changelog | pkg.go.dev | leather.sh | pate.sh

Local agent infrastructure in one stdlib-only Go binary.

Leather runs declarative agents on your workstation, server, or Raspberry Pi: scheduled jobs, one-shot runs, webhook-driven workflows, tool calling, and auditable outputs.

No Python stack. No hosted control plane. No broker, telemetry, or dependency pile.

cat > summarizer.agent.md <<'EOF'
---
name: summarizer
---
You are a concise planning assistant. Output bullet points only.
EOF

leather validate --agent-dir .
leather run summarizer.agent.md

See it run

Seventeen demos in examples/, each one make target away.

cp examples/env.example examples/.env
$EDITOR examples/.env
make example-02
make example-06

Measured, not asserted

Two claims carry this project, each with its evidence one click away:

  • The runtime doesn't get in the way. The same code path runs a profiled 100-webhook burst — 500 LLM calls, 965K tokens, five fan-out/fan-in stages — end to end in 190s at 6.5% avg host CPU and no measurable IO pressure. Leather isn't the bottleneck; the model is. → examples/11-high-volume-ci
  • The runtime is where the accuracy lives. The same frozen 4B model spans 62.4% → 81.6% on a 250-issue gold corpus depending only on the design around it — a 22-arm × 2-rig ablation with paired per-issue verdicts and a measured noise floor. The floor isn't the bare model; it's a bad harness. → findings in plain language: examples/14-sig-triage · every cell and verdict: matrix / verdicts · raw run archives committed — auditable without a GPU

What it does

Agents *.agent.md — Markdown front and a system prompt with 0-N turns and variable support.
Tools Skills, toolsets, MCP server support, and shell-mcp (make build-shell-mcp) for turning shell commands into agent tools.
Curings Bind agents to queues for flexible multi-stage routing.
Queues Filesystem FIFO — configurable depth, backpressure, concurrency, dead-letter routing, and single-use parameterized queues.
Workers Goroutines with hooks into queues.
Tannery Pipelines connecting agents, curings, workers, and artifacts, with fan-in / fan-out routing.
DevTools Stdlib-JS UI with session timeline, event inspector, curing flow diagram, and live SSE.
Notifications Telegram and Signal backends.

Build one

A complete agent:

---
name: summarizer
---
You are a concise planning assistant. Output bullet points only.

A schedule for it (*.lifecycle.yaml, optional):

agent: summarizer
schedule: "0 9 * * *"
model: llama3
prompt: Summarize the three most important things to do today.

Run it:

leather validate                                  # check everything parses
leather run ~/.leather/agents/summarizer.agent.md # run once
leather serve --pretty --stats                    # run on schedule

Chaining two agents behind a webhook — one triages, one reviews, an artifact comes out the other end — is the same primitives composed: see the GUIDE.md: two-agent pipeline recipe and examples/06-multi-agent-curing.

Install

From source:

git clone https://github.com/TGPSKI/leather
cd leather
make build && make build-shell-mcp
make install

With go install:

go install github.com/TGPSKI/leather/cmd/leather@latest
go install github.com/TGPSKI/leather/cmd/shell-mcp@latest

Verify the install — no LLM endpoint required:

leather --version    # prints version
make example-01      # runs a mock-LLM example end-to-end

Model and endpoint

Every command above needs a model and an LLM endpoint from somewhere. All three forms set the same values — flag wins over env var, env var wins over config.yaml:

# flag
leather run agent.md --model llama3 --llm-endpoint http://localhost:11434
# env var
export LEATHER_MODEL=llama3
export LEATHER_LLM_ENDPOINT=http://localhost:11434
# config.yaml
model: llama3
llm_endpoint: http://localhost:11434

leather speaks the OpenAI Chat Completions API, so cloud endpoints work the same way. The bearer token resolves inline value → pass → env var, in that order:

export LEATHER_LLM_API_KEY="sk-..."
leather serve --llm-endpoint https://api.openai.com --model gpt-4o-mini
# config.yaml + unix pass
llm_endpoint: https://api.openai.com
model: gpt-4o-mini
llm_api_key:
  pass: openai/api-key       # `pass show openai/api-key`
  env:  OPENAI_API_KEY       # fallback when pass is empty or unavailable

Go deeper

Pick your path by the question you're asking; each row starts approachable and descends as far as you want to go.

you want to… start here then
build an agent, pipeline, or tool docs/GUIDE.md — every file format, plus a recipe for each pattern above examples/ (17 runnable demos) · docs/CONVENTIONS.md (env-var reference) · docs/TEMPLATES.md
check the claims above examples/14-sig-triage — findings in plain language matrix / verdictsexperiment designclaim ledgerraw archives
see a real deployment docs/REFERENCE-TANNERY.md — six agents, four queues, running unattended, with measured run records and an honest A/B against a frontier control the system itself: TGPSKI/catnip/tannery
understand the internals docs/ARCHITECTURE.md — package layout and data flow docs/modules/ (per-package) · docs/GLOSSARY.md
contribute (human or agent) AGENTS.md — the routing table .subagents/ domain guides · CHANGELOG.md