Write a provider
A provider teaches AutoDev to drive one more agent CLI. It is one file, built from TypeScript, that turns a prompt into the CLI's arguments and the CLI's output into a result. This guide follows the template provider from the first line to the pull request.
What a provider does #
AutoDev never runs a model of its own. It runs the agent CLIs you already use, and a provider is the part that knows one CLI: which arguments to pass for a prompt, how to resume a session, and how to read what the CLI prints. An argv goes in, a result comes out.
A provider holds no operating-system logic. It does not find the program, open a shell or handle Windows paths: AutoDev's runner does that, the same way for every provider.
The starting point is the template, providers/template-codex, a real provider for OpenAI's codex. Copy its folder and rename it:
providers/<your-name>/ src/index.ts the source captures/ real calls to your CLI, recorded below test/ your own tests meta.json description, author, homepage provider.mjs the built file, the only file anyone installs
Install the kit in the repository: npm i -D @stefanolabs/autodev-provider-kit.
What it is handed, and what it cannot do #
Your provider's create(cfg, host) receives everything it uses in host:
host.runner(binary, args, onLine?, input?)starts the CLI.input, when you pass it, is written to stdin and the pipe is closed, so the CLI never waits on an open stdin.host.binaryis the CLI's resolved path on this machine.host.pinis the model and effort the person chose for this participant. Pass them through as they are: they are free-form strings, and a list of models is wrong the morning a new one ships.host.mcpis AutoDev's MCP server on a participant call, andnullotherwise. It is how the agent reaches the shared thread. Add it alongside the person's own servers, never with a flag that replaces their configuration.host.platformis the machine's platform, if your CLI's flags differ by it.
A provider file cannot do anything else, by design:
- No imports and no network. It imports only
@stefanolabs/autodev-provider-kit/provider, which the build bundles in. It has nofetch, noprocess, norequire. AutoDev checks the file before loading it, then runs it in a sandbox where none of those exist. - Only its own CLI. The runner starts the program the provider declares in
binary, and nothing else. - Limits come back in the result. When the CLI reports a usage limit, return it in
execute'srateLimitwith the time to come back.detectRateLimitis not called on a sandboxed provider, so it can returnnull.
The CLI your provider drives can still do whatever that CLI does. That is why a reviewer reads the arguments every provider passes.
Declare only what a capture shows #
capabilities lists what your CLI can do: live events, session resume, token reporting, a read-only mode and so on. Each one is false until a capture shows the CLI doing it. false means "not verified", never "absent".
The contract checks every claim against your captures. A capability you declare but your captures do not show is a failed clause, so start with everything false and turn on only what you have recorded.
Record your CLI #
The contract runs on real calls, so first register your provider locally and record it:
npx autodev-provider-kit build providers/<name>/src/index.ts -o providers/<name>/provider.mjs autodev providers add providers/<name>/provider.mjs autodev providers capture <name> hello --out providers/<name>/captures autodev providers capture <name> resume --out providers/<name>/captures autodev providers capture <name> tool-notice --out providers/<name>/captures
There are four scenarios:
hello: one plain call. It proves the session id, the exit code and the output.resume: a second call on the sessionhellostarted.tool-notice: a tool prints something that looks like a limit. It proves you read limits only where the CLI reports them, never from tool output.limit: a real usage limit. You cannot order one up, so save the output the next time it happens and turn it into a capture with--from-log. Skip it if your provider declares no limit detection.
Build, check, and one real turn #
npx autodev-provider-kit build providers/<name>/src/index.ts -o providers/<name>/provider.mjs npx autodev-provider-kit check providers/<name>/provider.mjs --captures providers/<name>/captures
check runs what AutoDev runs before it registers a provider: the gate on the file, the sandbox, and the twelve clauses of the contract on your captures. Each finding names a line or a clause.
Then write your own tests in test/. They are required, and they must cover at least 80% of the lines in src/: the arguments you build, the output you parse, the failure paths. The template's tests show the pattern, a host whose runner records the arguments instead of starting the CLI:
npx vitest run providers/<name>/test --coverage.enabled --coverage.provider=v8 --coverage.include="providers/<name>/src/**" --coverage.thresholds.lines=80
Last, run one real turn: add a participant on your provider in the AutoDev panel, start a run, and keep the line it posts on the thread. Captures prove the parsing; a turn proves the thread tools reach the agent.
Submit it #
Run npm run index to regenerate index.json, then open a pull request on stefanolabs/autodev-providers. The checklist asks for:
- a green contract on captures recorded from the real CLI;
- one real thread turn, as a screenshot or the
thread.jsonlline; - your tests passing at 80% line coverage of
src/; provider.mjsbuilt fromsrc/, never edited by hand (CI rebuilds it and compares byte for byte);meta.jsonfilled in, andindex.jsonregenerated.
A reviewer reads the arguments your provider builds, in full. Once it is merged, anyone can install it with autodev providers add <name> or from the panel's Community section.