Build AdaL

KINDAreplaces $20/mosaves $240/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A terminal coding agent whose hard problems are not the model calls but the harness around them: tools that cannot leak a secret or escape the repository, sessions that resume after a crash mid-tool-call, delegation that gives each sub-agent only what it needs, and a verification loop the agent cannot satisfy by weakening the tests.

estimated effort weekendthe files for this build are in the project pack

RuntimePython 3.12, one file per module, no frameworkProvidersAnthropic, OpenAI and Google behind one chat(model, messages, tools) functionToolsread_file, write_file, list_dir, run_shell and run_tests, confined to the repositorySessionsAppend-only JSONL under .agent/sessions with every call, result and costVerificationThe project's own test command after every edit, with a shown diff of any test change

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the agent, its tools and the test suite.

    Get it python.org or your package manager. open ↗

    Verify python3 --version prints 3.12 or higher

  2. API keyper token, and a long task can be several pounds

    Why Routing across model families is the point, and a single provider hides every seam the design depends on.

    Get it Per-token billing accounts with two of Anthropic, OpenAI and Google, keys in .env, and note the current published prices for the price file.

    Verify chat() returns from both providers and the recorded cost matches the price file

  3. have readyfree

    Why The verification loop is only meaningful against tests that can actually fail, and a toy project with one passing test exercises none of it.

    Get it A project of your own with at least fifty tests and a configured test command.

    Verify The test command runs from the project's configuration and at least one test can be made to fail

  4. have readyfree

    Why One where the implementation is wrong and the test is right, and one where the only way to go green is to weaken the test, are the two cases the loop must tell apart.

    Get it Write both by hand in the repository's test style.

    Verify The first ends fixed and the second ends stopped with the diff shown

  5. decidefree

    Why Cost is computed from it and a ceiling is derived from it, and a number remembered from a blog post is wrong more often than not.

    Get it Copy each provider's current published prices per million tokens into prices.json with the date checked, and decide a per-session and a daily ceiling.

    Verify prices.json has a checked_on date within the last month and both ceilings are set

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- sessions/<id>.jsonl · one event per line: kind, at, step, role, content, tool, args, result, tokens_in, tokens_out, cost_minor, model
- plan(step_n, description, acceptance_command, tools_allowed, state, attempts) · written by the planner, run one step per sub-agent
- scratchpad.md · the shared record sub-agents append to, and the only context a later sub-agent inherits
- approvals(at, command, cwd, decision, session_id) · every shell command shown, and what you said
- denied_paths · .env, keys, credentials and anything matching your patterns, refused by read_file before the model sees a byte
- prices.json(provider, model, input_per_million, output_per_million, checked_on) · maintained by you from the providers' published prices, dated, never assumed
- A tool call and its result are two events, so a crash between them shows on resume as a call with no result rather than as a call that never happened.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
ANTHROPIC_API_KEYsecretoptionalsk-ant-...redactedOne of at least two providers. Never read by the agent's own tools.
OPENAI_API_KEYsecretoptionalsk-...redactedOne of at least two providers. Never read by the agent's own tools.
GOOGLE_API_KEYsecretoptionalAIza...redactedOne of at least two providers. Never read by the agent's own tools.
AGENT_DEFAULT_MODELrequiredanthropic:claude-sonnet-4-5Overridden per session by --model. Provider prefix selects the module.
SESSION_DIRrequired.agent/sessionsAppend-only JSONL, flushed per event. Add it to .gitignore.
DENIED_PATTERNSrequired.env,*.pem,*.key,**/credentials*Refused by read_file before the model sees a byte. Err wide.
SESSION_COST_CEILING_MINORrequired500The run refuses the call that would exceed it, before making it.
PRICES_PATHrequired./prices.jsonYour dated copy of the published prices. Stale beyond a month warns.

The build, in order

  1. Tools that cannot reach what they should not

    The agent reads, writes and runs inside the repository and nowhere else, and never sees a secret.

    1. Keys from .env, model switch by flag, no provider code anywhere else.

      Files providers.pyconfig.py

    2. Resolve symlinks first; test with a planted fake key.

      Files tools.pyredact.pytests/test_secrets.py

    3. Print it, wait for y or n, record the answer.

      Files shell.pyapprovals.py

    done when · tick each as it passes
    watch out
    • The first thing a model does in an unfamiliar repository is read the configuration, and .env is configuration, so within minutes your provider keys are in a prompt on somebody else's server and in your own session log. Deny the files by name and pattern inside read_file, redact key-shaped strings from every tool result, and test both with a planted fake key.
  2. Sessions that resume after the worst moment

    A crash mid-tool-call is visible and recoverable, and every turn's cost is known.

    1. The crash that matters is the one after forty minutes.

      Files session.py

    2. A call without a result did not happen, as far as you can know.

      Files resume.pytests/test_resume.py

    3. Never a number in code; you maintain the file and its date from the published prices.

      Files cost.pyprices.json

    done when · tick each as it passes
    watch out
    • Writing the session to disk at the end of the run means the run that crashed after forty minutes of work leaves nothing, and the one that crashes is always that one. Append and flush per event, and on resume treat a tool call without a result as never having happened, because you cannot know whether it did.
  3. A planner whose steps can be checked

    Work is split into steps that each state how you would know they are done, and each runs in a fresh context.

    1. A step that cannot fail cannot succeed either.

      Files planner.pytests/test_plan_shape.py

    2. The step, the scratchpad, the named files. Assert it.

      Files subagent.pytests/test_context.py

    3. An agent that retries forever is spending your money on the same mistake.

      Files orchestrator.py

    done when · tick each as it passes
    watch out
    • Handing each sub-agent the entire conversation so far defeats the reason for splitting the work, costs a full context per step, and lets step six get confused by step two's abandoned approach. Give it the step, the scratchpad and the named files, and make the planner produce steps you can refuse when an acceptance command is missing or amounts to 'looks good'.
  4. Verification the agent cannot game

    Edits are tested automatically, and the only way to pass is to make the code work.

    1. From the project's own configuration, not a guess at the command.

      Files verify.py

    2. A loosened assertion is the pass that is not a pass.

      Files verify.pytests/test_no_test_weakening.py

    3. So the final report is what happened rather than what was planned.

      Files report.py

    done when · tick each as it passes
    watch out
    • Given a failing test and permission to edit, a model will sometimes loosen the assertion, mark the test as skipped or delete the file, and the run then reports success with the tests green. Diff the test files after every retry, show the diff, and treat a retry whose only change is to the tests as a failure that needs a human.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more dev tools.