Where results go
The model writes the content, the config picks the destination, and awaywork or your own notify hook does the write, never the model. The integrity rules in Safety never move. How far a result reaches is your call per rule, quiet by default.
Reach and ownership
Who sees the result, and whose thing it lands on:
| Reach | Your PR, issue or task | Someone else's PR |
|---|---|---|
| Only you | awaywork: report into the morning report, pending_review on your own PR (submittable only as a comment). Your hook: a note to yourself, like ntfy | awaywork: report, pending_review. Your hook: the same note |
| Visible, nobody asked to look | awaywork: draft_pr (default), push onto your PR's branch. Your hook: PR labels, a Notion page, a Slack message | awaywork: nothing, it stays private. Your hook: a Notion page, a Slack message |
| Pings someone | awaywork: pr, a ready PR, which asks the code owners. Your hook: reviewers | awaywork: nothing; you submit the pending review. Your hook: a Slack @mention |
The deliver values are in Delivery, set per rule in Queue rules.
Each deliver
draft_pr: the worker commits and writes.away/out/pr.md(first line the title), which later steps keep current. awaywork adds anAwaywork: <run id>trailer, pushes the new branch and opens one draft PR into that base. Nopr.md, no publish. Never into someone else's PR or a fork's: there a chain that could commit is skipped with the reason; a report still works.pr: adraft_prthat opens ready for review, pinging whoever a ready PR pings, code owners included. It stays a draft, saying why, when a step failed, stopped or never ran, it asked questions or saidcontinue,verifyfailed, a loop ended before itsuntilheld, or a gate fired.report: no step commits; each writes.away/out/report.md, and the chain's reports, joined, go into the morning report.pending_review: areportthat also lands on the PR, anyone's or a fork's: the last report and the line comments in.away/out/review.jsonbecome your pending review at the commit the clone read, seen only by you until you submit it. If GitHub refuses a line comment (one off the diff, say), they all go in the body. When a step failed, stopped or never ran, or GitHub refuses the review (you have one pending there already, say), the report goes alone with the reason.plan: areportwhose step also writes.away/out/plan.yml: Plans.push: the commits andpr.md, pushed with the trailer onto your own open PR's branch as a fast-forward. The PR body isn't touched;pr.mdgoes into the morning report. Nopr.md, no push. Undersyncthe one commit is awaywork's merge of the PR's base; a worker runs only to resolve a conflict, without committing. It pushes only while (push):- the PR is yours, open, in the repo, without auto-merge;
- its head is still where the clone started;
- its branch isn't on a fork, the default branch, protected, or someone else's open PR's.
A PR's body gets its items' link lines and a footer naming awaywork, the run and the unit's items, which is how the next plan links it back.
A step's one-word status and verdict files are in Skills.
Built in
- Ready PRs:
deliver: pr, a draft still when the chain went wrong, a step asked or saidcontinue, or a gate fired. A draft a later run finishes turns ready. - Decision cards: a fired gate tops the PR body with a "Needs a decision" card, or a plan or report rule's post for its own gates; with none fired, a
Gates: none fired (…)line. On apushthe body isn't awaywork's, so the card tops the report's summary and the push still happens. - Review comments:
pending_reviewleaves the report and line comments as your pending review, unseen until you submit it. - Questions: posted as a comment on your own item, your reply the answer; commits made first open as a draft that says so. On an item not yours they stay in the report.
- Plans:
deliver: planpostsplan.yml's tasks under the report and contract on your card and waits: a reply startingapproveapproves, anything else replans;wait: falsegoes ahead unless a gate fires. - Posts that wait: a
reportrule withwait: trueposts on your card and waits like a plan, holding itson_donemove; yourapprovehands the card to the rule whosewheresaysapproved: <skill>. - Lean posts: with a store, a plan or report posts
summary.mdand a link per file; the next unit gets the files back on any machine, and an edited file counts as feedback. - Task PRs: each approved task opens its own PR, per its
plannedrule'sdeliver, in the card's repo or another the config names, withPart of <card>instead ofCloses. - Task posts: a task has no item, so it writes to the card: questions headed
Questions from task api, a reporting task's report headedResult of task qa, and aplannedrule'son_donemove. on_done:movesends your own items to a status, state, section or label once the chain published, never someone else's PR;comment: resultfirst posts the result (a report, or a link to the PR) with aStatus: doneline. A report that saidcontinuepostsStatus: continue (1 of 3)and runs again.
Notify
notify.command runs as you, with your environment, on two events in AWAYWORK_EVENT:
run, when a run ends, dry runs included:AWAYWORK_REPORTis the morning report's path, withreport.jsonbeside it, andAWAYWORK_RUN_IDthe run.unit, for every step of a unit once it published, before the next unit. None on a dry run; Ctrl-C stops the running one and fires no more.
notify: # a line per step
command: >-
[ "$AWAYWORK_EVENT" = unit ] || exit 0;
echo "$AWAYWORK_UNIT $AWAYWORK_STATUS $AWAYWORK_PR_URL" >> ~/awaywork.logThe command gets both events, so filter as above. secrets names the env vars it reads: workers never see them, and Actions passes them from repository secrets. Both events have AWAYWORK_RUN_ID; a unit event also has:
| Variable | Holds |
|---|---|
AWAYWORK_UNIT, AWAYWORK_SKILL, AWAYWORK_STATUS | The step (acme-api-12-review-1), its skill, how it ended (done, failed, skipped...) |
AWAYWORK_PR_URL | On every step of a unit that opened a PR; never on a push, so a hook can't touch your own PR |
AWAYWORK_REPORT | What the step wrote: its report, or the PR body |
AWAYWORK_ITEM_URL, AWAYWORK_ITEM_KEY, AWAYWORK_SOURCE | One line per item, in order |
AWAYWORK_REPO | owner/name |
AWAYWORK_VERDICT, AWAYWORK_OUT_DIR | The step's verdict, and its kept .away/out/, which also holds earlier steps' files: check $AWAYWORK_SKILL first |
There are no built-in integrations. A failure or a run over a minute is logged (notify failed for acme-api-1: Command failed with exit code 3: ...) and the run still succeeds; anything left in the background is stopped. Recipes, ntfy, Slack and Notion among them, are in Where results go.
PR labels, reviewers and ready for review
Ready for review is deliver: pr. Otherwise a PR gets the agent's title and body, no labels or reviewers, into the base awaywork picked. gh in the hook adds the rest:
notify:
command: |
set -e
[ "$AWAYWORK_EVENT" = unit ] && [ -n "$AWAYWORK_PR_URL" ] || exit 0
gh pr edit "$AWAYWORK_PR_URL" --add-label awaywork
# every step of the PR fires: ask octocat once, and never on a draft
skip=$(gh pr view "$AWAYWORK_PR_URL" --json isDraft,reviewRequests -q '.isDraft or any(.reviewRequests[]; .login == "octocat")')
[ "$skip" = false ] || exit 0
gh pr edit "$AWAYWORK_PR_URL" --add-reviewer octocatset -estops at a failinggh; the next step tries again.--base developmoves the base too. Leave it out on a plan's stacked tasks and on a rule that takes up an awaywork PR: their PRs sit on another PR's branch, and moving the base breaks the stack.- It's your token, not a worker's. A reviewer, and the CODEOWNERS a ready PR asks, get notified: treat that like a comment you'd post.
Examples
Each is a notify block. A config has one notify.command, so put several in a script and point command at its full path. The unit event fires for every step, so each recipe first picks its steps. AWAYWORK_ITEM_URL, AWAYWORK_ITEM_KEY and AWAYWORK_SOURCE hold one line per item; most units have one.
- The morning report on your phone
- A Notion page per plan
- A Slack message when a review is ready
- Acting on a skill's own output
What awaywork won't do
- Post to Notion or Slack itself: every service has its own API and token, and your hook covers it in a few lines, with your token.
- Submit a review, approve, or comment on someone else's PR: its author wrote what the model read, so can steer what it says. A pending review waits for you to read it.
- Let a skill pick where its result goes: a skill writes into
.away/out/and holds no write token. The rule'sdeliverand your hook decide.