Skip to main content

Quickstart: ASDD with Goose

Status: alpha. This operate layer is usable and dogfooded, but its recipes and interfaces may still change before a stable release. The standard is a separate v0.1 draft.

Zero to a governed agentic-dev loop. You need Python 3.9+ and Goose. No paid model account is required to try it - a local model via Ollama works for free.

Adopting into a project that already exists? Read adopt-existing-project alongside this. A mature repository already has a spec layout, a changelog format and a house style, and the agents must be told about them or they produce work in the wrong place.

ASDD's operate layer runs two ways: your own operator (any runtime satisfying agents/runtime.md) or Goose (this guide). The standard mandates neither.

1. Get the CLI on your PATH

Clone ASDD, then either symlink the launcher (pip-free) or install it:

ln -s "$PWD/asdd_cli.py" ~/.local/bin/asdd # pip-free; or, with a recent pip: pip install -e .

No install needed either - python3 asdd_cli.py <command> and bash cli/init.sh work straight from the checkout. asdd --help lists the commands.

2. Install into your repo

asdd init --goose /path/to/your-repo

--goose scaffolds the govern config and the operate kit: the recipes, the four deterministic gates, and the asdd-mcp MCP extension. Existing files are skipped unless --force, so it won't clobber a customised repo. It also sets the project's contribution lanes to the architecture-aligned operate taxonomy (govern/operate/know/assure/standard/docs/chore); see contribution lanes for an operated project to trim or override them.

3. Configure a model

goose configure

Pick any provider Goose supports - Anthropic, OpenAI, Google, any OpenAI-compatible endpoint, or a local model. The recipes are provider-neutral; you set the model per run. For a free local try:

ollama pull qwen3:8b

Then assign a model to each agent role. Do not hand-edit .asdd.yml blind - the wizard prompts for each role, keeps the developer distinct from the test models (the one hard rule), and prints the run commands and CI secrets for the models you picked:

asdd setup # interactive; or --set test_author=A --set test_runner=B --set developer=C

Prefer a page to a prompt? asdd setup-dashboard opens the same thing as a local (127.0.0.1) web form.

A known-good roster to start from

The recipes are provider-neutral, but not every model works behind every provider, so trial and error costs you an afternoon. This roster is proven end to end and is a safe starting point:

RoleModelWhereWhy
developeryour own (e.g. Opus 4.8)its native provider (bring your own)builds the code; native provider translates the tools correctly
reviewerGLM-5.2Runware (OpenAI-compatible)strong open-weight; tolerant of Goose's tool schemas
test_author / test_runnerKimi K2.6Runwarea different family from the developer (the heterogeneity rule)
documentation / interactionGLM-5.2 or Kimi K2.6Runwareeither works; just keep them off a model that rejects tools

The rule behind it: a tool-using role needs a tool-tolerant provider. Some OpenAI-compatible providers reject a no-argument tool's empty schema (a 400 on tools), so a capable model can still fail behind a strict provider even though the model itself is fine. GLM-5.2 and Kimi K2.6 accept them; a bring-your-own developer should run on its model's native provider, where the tools translate correctly. For Runware specifically, set supports_streaming: false on the provider (see Troubleshooting). Both traps have troubleshooting entries if you hit them on a different provider.

Or let an agent walk you through it. The setup recipe reads asdd-kit.yml - the kit map: every role, its recipe, its model key, where it runs, and the invariants - so it starts oriented instead of reading the kit to work it out. It tells you what is configured, what is missing, and does the safe parts for you:

goose run --recipe recipes/setup.yaml --model <your model>

That model is also your developer: the developer is bring-your-own, so your own Goose session is it.

4. Check the kit is valid

Run the preflight first. It checks the things that fail silently otherwise: whether Goose and (if you chose spec_tool: openspec) the openspec CLI are actually reachable, whether your roster obeys the one hard rule, and whether the recipes are in place. Crucially it tells apart "not installed" from "installed but not on your PATH" - the latter reads as "missing" to a bare which and sends people reinstalling a tool they already have.

asdd doctor # or: asdd doctor path/to/.asdd.yml

It never changes anything; it reports each item as OK, a warning, or a blocking issue, with the exact next step. Then confirm the recipes validate against your installed Goose:

goose recipe validate recipes/test-runner.yaml
goose recipe validate recipes/interaction.yaml
# -> "recipe file is valid" for each

5. Prove it runs (free, no keys)

Confirm a Goose agent actually loads the gates and calls one, against a local model:

goose run --provider ollama --model qwen3:8b \
--with-extension "python3 cli/asdd-mcp.py" \
-t 'Call the merge_eligibility tool with paths=["crypto/aes.py"], protected="**/crypto/**", posture="earned-automerge". Report only the verdict.'

The agent loads the asdd-gates extension, calls the gate, and reports human-approve - a protected path never auto-merges. If you see that, the operate layer works end to end.

6. Stand up the rest of the roster

The reviewer and the gate call are proven above. The test, documentation, and interaction agents are not done until each has run against something real. Do not read the commands below as "set up"; read them as "run it, then confirm it did the thing." Each runs with its own model (keep the test agents distinct from whatever builds the code, developer != test_author, test_runner), and the recipe's own instructions are the prompt, so you pass --param, not -t.

Run each agent with asdd operate-run, not goose run directly. The wrapper runs the recipe and then records the action in the audit ledger deterministically: the agent writes its outcome to a result file and the wrapper turns that into a record, so a provider timeout part way through a long run cannot silently lose the action. It records the role, so the interaction agent runs as --role spec (the role it records under).

Test agents. Authoring the tests and executing them are two jobs, and ASDD splits them: test-author.yaml writes the coverage the change needs from the spec, and test-runner.yaml runs the suite and reports pass or fail. Both run on models distinct from the developer's, so their blind spots do not line up with the code's. Before running the runner, decide who actually executes the suite and where: the agent itself, CI, or the Goose developer builtin shell. The recipe drives the check; you point it at the executor you chose.

asdd operate-run --role test-runner --recipe recipes/test-runner.yaml --model <test-runner-model> --param pr=<PR>

Proven when it reports a real pass or fail on a real PR, not a template run.

Documentation.

asdd operate-run --role documentation --recipe recipes/documentation.yaml --model <doc-model> --instructed-by you --param change_ref=<PR>

Proven when it writes a correct doc or knowledge update for an actual change.

Interaction. platform=web below is a placeholder. The real work is the platform binding (Slack, Discord) and proving the agent answers from project knowledge and routes an idea into the spec pipeline via the spec_check gate.

asdd operate-run --role spec --recipe recipes/interaction.yaml --model <public-model> --param platform=web

Proven when it answers one real question from project knowledge and routes one real idea in as a validated spec. Interaction is on-demand: you run it (or bind it to a surface) when you want it; it does not fire on its own. On an untrusted public surface use recipes/interaction-public.yaml, which is execution-free.

Operator-run agents (triage, support, contributor & merge review). These four are fixed-prompt agents, not recipes, and they are not part of the automatic PR gate: you run them on demand with asdd run-agent, which drives the agent through the model and records the action, safely (the input is fenced as untrusted data, exactly as the review gate does).

asdd run-agent triage new-issue.txt # propose labels + a welcome (allow-list enforced by policy-check)
asdd run-agent review-contributor change.diff # suggestions to bring a change to ready
asdd run-agent review-merge merge-evidence.txt # the independent final check before a human merges
asdd run-agent support question.txt # answer from the project's own knowledge

Proven when each returns its structured output on a real input. With no model wired it prints a labelled dry run. See cli/README.md (run-agent).

Automated on trusted input. Two agents also run themselves after a human merges, where the input is trusted: the asdd-docsync workflow (documentation) and the asdd-test workflow (a post-merge regression run of the test agent). Both are installed by init --goose, both dry-run until a model is wired, and both refuse to run on untrusted pre-merge input. The tester is deliberately not run automatically on an open PR: executing a stranger's code needs an egress-free sandbox this kit does not ship (see operate-in-ci.md); author and run tests in the produce loop instead.

The developer is bring-your-own and is exempt: a contributor connects their own coding agent to build a change. "Set up" means every agent above has run against a real artifact, not that the reviewer works and the rest are listed.

How it fits together

  • A contributor (or your own agent) builds a change and opens a PR.
  • The test author extends the suite from the spec, and the test runner (both on models distinct from the developer's) runs it.
  • The CI review gates (the govern layer, .github/asdd/) review it; a human merges.
  • The interaction agent brings public ideas in as validated specs (via the intake gate).

The gates are callable directly too: asdd merge-eligibility ..., asdd spec-check ..., asdd validate.

Enforce the one hard rule

asdd check-models --strict # fails if a test model == developer

Share the recipes

To run the agents by bare name instead of a full path, or hand someone a single recipe as a link, see share and run the recipes by name.