Skip to content

For course authors

Quickstart

Copy a small tested course, check it and see what a pass and a fail look like.

A course is a folder of Markdown files, a few check programs and one rubric. This guide builds the smallest complete one, a course named quickstart that teaches a learner to build a one-file agent and explain it. Every file below is rendered from the example course that the agentcourses/agentcourses repository tests, so what you copy is what was proven.

The course you write is addressed to the tutor, the agent that teaches it. Only each lesson’s ## Goal is read to the learner as written. The course format lists the headings a runner looks for.

Clone the agentcourses/agentcourses repository and install the Python and uv versions named in its README. The top of that clone is the checkout root. Run every command marked checkout root from there. Choose any empty directory for the course itself. It is your course folder, and it is separate from the project a learner works in. Where this guide says “the course folder”, use that directory.

Folder names matter: the folder name must equal the course’s name, so the folder here is called quickstart (course shape).

  1. Run this in your chosen empty directory, which will hold the course folder.

    Terminal window
    mkdir -p quickstart/lessons quickstart/tutor quickstart/checks/fixtures/final-check/pass quickstart/checks/fixtures/final-check/fail

    The layout is described in the course layout.

  2. Save this as quickstart/COURSE.md in the course folder. Its frontmatter names the course; its body is the page a learner reads first.

    ---
    name: quickstart
    description: Build a one-file agent and explain it. For beginners.
    version: "1.0.0"
    license: Apache-2.0
    project: [own]
    ---
    # Build a small agent
    You'll build a small agent.
    ## Outcome
    `agent.py`: an agent that passes `final-check`.
    ## Lessons
    1. [Meet the agent](lessons/intro.md)
    2. [Make the agent](lessons/make.md)
    3. [Finish and explain](lessons/finish.md)

    The project: [own] line means the learner works in the project they already have open. See the project field for the other options.

  3. Save each file in quickstart/lessons/ in the course folder. The file name is the lesson id, and the order of lessons is the order listed in COURSE.md.

    First, quickstart/lessons/intro.md:

    ---
    title: Meet the agent
    stage: understand
    calls:
    - id: choose-tool
    ask: Which tool will your agent call first?
    ---
    ## Goal
    You can say what an agent tool is.

    Then quickstart/lessons/make.md:

    ---
    title: Make the agent
    stage: build
    checks: [agent-runs]
    objectives:
    - id: agent-runs-ok
    text: The agent runs
    by: agent-runs
    ---
    ## Goal
    Your agent runs.
    ## Build
    Ask the learner how to start the agent, then create `agent.py` with them.

    Last, quickstart/lessons/finish.md. The last lesson is the only one with the demonstrate stage (stages).

    ---
    title: Finish and explain
    stage: demonstrate
    checks: [final-check]
    calls:
    - id: choose-check
    ask: Which behaviour will the final check protect?
    objectives:
    - id: agent-passes
    text: The agent passes the final check
    by: final-check
    - id: agent-explained
    text: The learner explains the agent
    by: explain-back
    ---
    ## Goal
    You can show the agent works and say why.
    ## Explain back
    Explain which tool your agent calls and why you chose it.

    Together the lessons show two habits worth copying. The choose-tool call in intro.md and the choose-check call in finish.md are decisions only the learner makes (calls). The make lesson’s ## Build section is an instruction to the tutor, not to the learner.

  4. Save this as quickstart/checks/checks.yaml in the course folder. It declares one command check and one observe check (check declarations).

    - id: final-check
    run: python "$AGENT_COURSE_DIR/checks/final_check.py"
    verify: agent.py defines an agent
    timeout: 30
    network: false
    - id: agent-runs
    kind: observe
    verify: agent.py exists and defines an agent
  5. Save this as quickstart/checks/final_check.py in the course folder. A check runs with the learner’s project as its working directory, so it reads agent.py by a relative path. It reads the file without running it.

    """Check that the fixture project declares an agent without importing its code."""
    import ast
    import json
    from pathlib import Path
    path = Path('agent.py')
    try:
    tree = ast.parse(path.read_text(encoding='utf-8'))
    passed = any(
    isinstance(node, (ast.Assign, ast.AnnAssign))
    and any(isinstance(target, ast.Name) and target.id == 'agent'
    for target in (node.targets if isinstance(node, ast.Assign) else [node.target]))
    for node in tree.body
    )
    except (OSError, UnicodeError, SyntaxError):
    passed = False
    print(json.dumps({
    'check': 'final-check',
    'status': 'pass' if passed else 'fail',
    'path': 'agent.py',
    'line': 1,
    'message': 'Agent declared.' if passed else 'No agent declaration found.',
    'fix': 'Define an agent variable in agent.py.' if not passed else '',
    }))
    raise SystemExit(0 if passed else 1)
  6. Every command check needs a project that passes and a project that fails (rules every check follows). Save this as quickstart/checks/fixtures/final-check/pass/agent.py in the course folder:

    agent = object()

    Save this as quickstart/checks/fixtures/final-check/fail/agent.py in the course folder:

    value = None
  7. Save this as quickstart/tutor/finish.rubric.md in the course folder. The rubric belongs to the final lesson and is never shown to the learner (rubric grammar). The explain-back guide explains how it is used.

    ---
    pass: 2 of 3
    ---
    - **Names the output type** and says why a typed result is safer than prose
    - **Describes the tool call**: what triggers it and what it returns
    - **Names one failure mode** and how the checks would catch it
  8. Save this as quickstart/feedback.yaml in the course folder. It is optional, and it declares the only feedback the course may ask for (declared only).

    rating: at-end
    stuck: {after_failures: 3}
    questions:
    - id: next-step
    ask: Which topic would you choose next?
    options: [Tools, Checks]
  9. Run this at the checkout root, replacing the path with where your course folder is.

    Terminal window
    uv run --locked python tools/check_contracts.py --example /path/to/quickstart

    A correct copy prints contracts: 0 errors, 0 warnings and exits zero.

  10. This runs the program the way a runner would, with the project as the working directory. Run it from inside the course folder’s parent directory, using a plain python3. It changes nothing.

    Terminal window
    COURSE="$PWD/quickstart"
    cd "$COURSE/checks/fixtures/final-check/pass"
    AGENT_COURSE_DIR="$COURSE" AGENT_COURSE_PROJECT="$PWD" python3 "$COURSE/checks/final_check.py"; echo "exit $?"
    cd "$COURSE/checks/fixtures/final-check/fail"
    AGENT_COURSE_DIR="$COURSE" AGENT_COURSE_PROJECT="$PWD" python3 "$COURSE/checks/final_check.py"; echo "exit $?"

    The first project exits 0 and reports pass. The second exits 1 and reports fail with a path and a fix. The checks guide explains what each exit code means.

When a learner takes the course, each lesson follows the same loop: the tutor says the Goal, builds with the learner, puts each call to the learner, runs the lesson’s checks, reviews the results and, in the last lesson only, asks for the explain-back (the teaching loop). While building, the tutor shows each change and says why, and rereads a file just before editing it so a hand edit by the learner is never overwritten (building together). Write your lessons so the tutor can do all of this. The tutor may type the code, while the learner owns the decisions.

A public validate, test or lint command and a released /learn command are planned. They are not available, so nothing in this guide depends on them. Until they exist, the checkout commands above are the only tooling, and they run only from a clone of the agentcourses/agentcourses repository.