Official GitHub Actions for zot, the autonomous software factory. zot takes work orders, not prompts: a small YAML file with the durable objective, the acceptance criteria that define "done", and the constraints the work must hold to. Each order becomes one unattended run that plans, edits, runs and verifies until the work is done - which is exactly the shape of a CI job.
Available actions:
setup- install thezotbinary from a release and put it onPATHrun- run work orders: committed order files, an order written inline in the workflow, or both, with an optional inline zot configurationissue- turn a GitHub issue into a work order, drafted by zot from the raw issue, and run it
1. Run orders that are already in the repository. Orders are files, so
commit them under .zot/orders/ and let CI run them:
- uses: openzot/actions/run@v0
with:
orders: .zot/orders/*.yaml
provider: zai # zot's default pair; any OpenAI-compatible provider works
model: glm-5.2
env:
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}The model is chosen by provider + model (or a config block, below) and
paid for by the provider's key passed through env:. With none of them set
zot falls back to its built-in default, zai + glm-5.2, so the ZAI_API_KEY
alone would do - but say it.
A project's orders and the ledger of what has been run from them live together
under .zot/ - .zot/orders/ and .zot/records/, keyed by the order's content
hash. Commit the ledger with the work and an order that already settled is
skipped on the next run; edit the order and it runs again. See
examples/orders.yaml.
2. Use GitHub issues as the source of orders. The issue action reads
one issue - raw, title and body as written - hands it to zot new --draft,
which surveys the checkout and has the model write the order (objective,
acceptance criteria, constraints), and then runs that order to completion.
The issue comes from the event that triggered the workflow: label an issue
zot, and github.event.issue.number is the issue to work on (any issue can
be named with issue-number: instead, e.g. from a workflow_dispatch input):
on:
issues:
types: [labeled]
jobs:
order:
if: github.event.label.name == 'zot'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: openzot/actions/issue@v0
id: zot
with:
issue-number: ${{ github.event.issue.number }} # the default; shown for clarity
provider: zai
model: glm-5.2
max-iterations: 300
env:
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
# the checkout now holds the work; open it as a PR that closes the issue
- uses: peter-evans/create-pull-request@v8
if: steps.zot.outputs.changed == 'true'
with:
branch: zot/issue-${{ github.event.issue.number }}
title: ${{ steps.zot.outputs.issue-title }}
body: |
Closes #${{ github.event.issue.number }}
${{ steps.zot.outputs.summary }}issue takes the same configuration inputs as run and adds the drafted
order (order-path) and the issue to its outputs. See
examples/issue.yaml for the full workflow, with a
comment back on the issue, and the issue README.
3. Write the order inline. Good for recurring work on a schedule - a weekly dependency sweep, a nightly docs check:
- uses: openzot/actions/run@v0
with:
order: |
objective: |-
update every dependency to its latest compatible release
acceptance:
- the lockfile is updated and `npm test` passes
constraints:
- no major version bumps
env:
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}See examples/inline.yaml.
Long orders across several jobs. zot continues an order whose last run did
not conclude. With cache-sessions: true the session logs survive the runner,
so a run cut short by a step timeout is picked up by the next one - see
examples/resumable.yaml.
Everything zot reads from a config file can be given inline, so a workflow is self-contained:
- uses: openzot/actions/run@v0
with:
orders: .zot/orders/*.yaml
config: |
default_provider: anthropic
agent:
model: claude-sonnet-5
max_iterations: 200
providers:
anthropic:
api_key: $ANTHROPIC_API_KEY
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}config is the same schema as
zot.example.yaml.
Reference secrets as $VAR and pass them through env: - never paste them.
Guidance for the agent is not configuration: it lives in the repository's
AGENTS.md and .skills/, which zot reads from the working directory. Single settings also
work as ZOT_* environment variables (ZOT_AGENT_MODEL, ZOT_DEFAULT_PROVIDER,
…) or as the provider / model / max-iterations inputs.
zot is fully autonomous and has real file-write and shell access to the working directory - the runner's checkout. That is the point, and it is also the blast radius:
- Provider keys passed through
env:are scrubbed from the environment of the agent's shell commands by zot itself. Any other secret in the job's environment -GITHUB_TOKENincluded - is readable by the task. Give the job the leastpermissions:that work, and keep tokens for steps that need them (opening the PR) rather than the whole job. - Only run orders from sources you trust: an issue body is an instruction to an
agent with shell access. Gate the issue flow on a label that only maintainers
can apply, or on
github.event.issue.author_association. - Set
max-iterationsand a jobtimeout-minutesfor unattended runs. - Prefer opening a pull request over pushing to a branch: the diff is the review.
Versioning is driven by the root VERSION file.
- Update
VERSIONwhen you want to publish a new release. - Merge the change to
mainin theopenzot/actionsrepository. - The release workflow creates the immutable
vX.Y.Ztag and updates the floating major tag such asv0.
Consumers should normally pin to a major tag such as @v0. The actions
install the latest zot release by default; pin version: for
reproducible runs.