|
| 1 | +# Contributing — add your own starter |
| 2 | + |
| 3 | +This repo is a **GitHub template** (click *Use this template*) and a set of |
| 4 | +worked examples that all follow one shape. Adding your own starter — for Build |
| 5 | +Day or after — means copying that shape. Here it is. |
| 6 | + |
| 7 | +## Anatomy of a project |
| 8 | + |
| 9 | +``` |
| 10 | +projects/<theme>/<name>/ |
| 11 | +├── agent.py # the entry point + the run() contract |
| 12 | +├── skills/<skill>/SKILL.md # one validated skill (+ optional scripts/ references/ assets/) |
| 13 | +├── evals/evals.json # the house eval method (with vs without skill) |
| 14 | +├── fixtures/ # offline fallback for every networked tool |
| 15 | +└── docs/MODEL_SELECTION.md + docs/ADLC.md |
| 16 | +``` |
| 17 | + |
| 18 | +The gentlest reference is [`fridge-whisperer`](projects/everyday/fridge-whisperer/) |
| 19 | +(no network, ~80 lines). Copy it and rename. |
| 20 | + |
| 21 | +## The one contract |
| 22 | + |
| 23 | +Every `agent.py` exposes: |
| 24 | + |
| 25 | +```python |
| 26 | +def run(task: str, skill=DEFAULT_SKILL): ... # returns an AgentResult (or anything with .text) |
| 27 | +``` |
| 28 | + |
| 29 | +`skill=None` is the **without-skill baseline** — the same code path, no second |
| 30 | +branch. That's what the eval runner toggles. Every `agent.py` also starts with |
| 31 | +the self-locating bootstrap so `python agent.py "..."` works from anywhere: |
| 32 | + |
| 33 | +```python |
| 34 | +HERE = Path(__file__).resolve().parent |
| 35 | +sys.path.insert(0, str(next(p for p in HERE.parents if (p / "agentkit").is_dir()))) |
| 36 | +from agentkit import run_agent, tool |
| 37 | +``` |
| 38 | + |
| 39 | +## The harness (`agentkit/`) |
| 40 | + |
| 41 | +```python |
| 42 | +from agentkit import run_agent, tool, chat, load_skill, cascade |
| 43 | + |
| 44 | +@tool # schema comes from the signature + docstring (the docstring is a prompt) |
| 45 | +def get_thing(query: str): |
| 46 | + """What it does, and WHEN to use it.""" |
| 47 | + return f"sentence-shaped result for {query}" # small models parse sentences better than bare values |
| 48 | + |
| 49 | +r = run_agent("the task", tools=[get_thing], skill=DEFAULT_SKILL) # the loop |
| 50 | +r.text, r.cost_usd, r.usage, r.tool_calls # everything measured |
| 51 | +``` |
| 52 | + |
| 53 | +`chat()` for one-shot calls, `cascade()` for cheap-first routing, `run_agent()` |
| 54 | +for the tool loop. Provider is one env var (`MODEL_PROVIDER`); see |
| 55 | +[docs/SETUP.md](docs/SETUP.md). |
| 56 | + |
| 57 | +## House rules (these earn rubric points) |
| 58 | + |
| 59 | +- **Zero/low-arg tools, sentence-shaped returns.** A 3B local model is the |
| 60 | + default target; keep tools simple. |
| 61 | +- **The fixture rule.** Every networked tool checks `AGENT_OFFLINE` and falls |
| 62 | + back to `fixtures/` on *any* exception, with a one-line notice to stderr. |
| 63 | + Evals always run offline so numbers are reproducible. |
| 64 | +- **System prompt = role only.** All format/rules live in the SKILL.md, never |
| 65 | + in `agent.py`. |
| 66 | +- **Skill anatomy:** `name` == directory name; a trigger-rich `description` |
| 67 | + (what + when); body sections `## Defaults` / `## Workflow` / `## Gotchas` / |
| 68 | + `## Output template`. Validate: `uv run agentskills validate skills/<name>`. |
| 69 | +- **Assert outcomes, not rituals.** Eval the brief's *content*, not a magic |
| 70 | + phrase the model happens to print. |
| 71 | +- **Budget:** ~300 lines of code per project (the flagship gets ~500). Readable |
| 72 | + beats clever. |
| 73 | + |
| 74 | +## Before you push |
| 75 | + |
| 76 | +```bash |
| 77 | +make verify # the no-model matrix (tests, validate, selftests, lint) — also what CI runs |
| 78 | +make smoke # every project answers offline on your local model |
| 79 | +make evals # full eval pass-rate deltas (needs a local model; slow) |
| 80 | +``` |
| 81 | + |
| 82 | +CI runs `make verify` on every push and PR. Keep your skill's eval delta ≥ 0, |
| 83 | +fill `docs/MODEL_SELECTION.md` with the numbers you measured, and you've cleared |
| 84 | +the bar. Then add a row to the picker table in the top-level [README](README.md). |
| 85 | + |
| 86 | +By contributing you agree your work is MIT-licensed, like the rest of the repo. |
0 commit comments