Skip to content

Commit

Docs: automations

A guide to .g1t/automations: triggers, schedules, conditions, steps, the {{ }} names, the rules every run keeps, and the API. The MCP reference and llms.txt list the four new tools.

syntaqxcommitted Parente109990Browse files
5 files+262−10/5 viewed
+1−0
7777 { label: 'Integrations', slug: 'guides/integrations' },
7878 { label: 'Model providers', slug: 'guides/models' },
7979 { label: 'Webhooks', slug: 'guides/webhooks' },
80+ { label: 'Automations', slug: 'guides/automations' },
8081 ],
8182 },
8283 {
+236−0
1+---
2+title: Automations
3+description: Rules committed to a repository that act when something happens, such as commenting, labelling, putting an agent on an issue or posting to chat.
4+---
5+
6+An automation is a rule kept in the repository, in
7+`.g1t/automations/`. It says what starts it, what must be true, and the
8+steps to take:
9+
10+```yaml
11+# .g1t/automations/bugs.yml
12+name: Put an agent on every bug
13+on: issue.opened
14+if:
15+ labels: bug
16+do:
17+ - comment: "Thanks, {{actor}}. A g1t agent is on it."
18+ - assign_agent
19+```
20+
21+Commit that file to the default branch and, from the next issue opened
22+with the label `bug`, g1t answers it and starts an agent on it. Change or
23+delete the file and the automation changes with it.
24+
25+Because automations are files, they are reviewed in pull requests like
26+any other change. Each repository can have up to 50.
27+
28+## See them run
29+
30+Open the repository's **Automations** page, in its sidebar. Each automation
31+is listed in words, such as *On issue.opened, if labelled bug: comment,
32+then put a g1t agent on it*, with its last run. A file g1t cannot read is
33+listed too, with what is wrong with it.
34+
35+**Recent runs** lists the last 50 runs. Open a run to see what started it,
36+and either how each step went or why the run was skipped.
37+
38+Members of the workspace can also:
39+
40+- **Run now**: run it straight away, on an issue or pull request if you
41+ give its number. This works for any automation, whatever starts it.
42+- **Turn off** and **Turn on**: stop it without changing its file. It
43+ stays off when the file changes.
44+
45+## What starts it: `on`
46+
47+| `on` | Starts it |
48+| --- | --- |
49+| An event, such as `issue.opened` | Whenever that happens in the repository. |
50+| A list, such as `[pull.merged, pull.closed]` | Whenever any of them happens. |
51+| `schedule: "0 9 * * mon"` | On a cron schedule, in UTC. |
52+| `manual` | Only by **Run now** or the API. |
53+
54+The events are the same as [webhooks'](/guides/webhooks/#events):
55+
56+| Event | When |
57+| --- | --- |
58+| `git.push` | A branch moved. |
59+| `issue.opened`, `issue.updated`, `issue.assigned`, `issue.closed`, `issue.reopened` | An issue changed. |
60+| `comment.created` | A comment or review on an issue or pull request. |
61+| `pull.opened`, `pull.ready`, `pull.updated`, `pull.merge_requested`, `pull.merged`, `pull.closed` | A pull request changed. |
62+| `checks.completed` | An issue's acceptance checks finished on a pull request. |
63+| `review.completed` | A g1t agent reviewed a pull request. |
64+| `queue.changed` | The merge queue changed. |
65+
66+A schedule has five fields: minute, hour, day of the month, month and day
67+of the week. Each field takes `*`, a number, a list (`1,15`), a range
68+(`1-5`) or a step (`*/15`, `0-30/10`). Days of the week also take names,
69+`sun` to `sat`.
70+
71+| Schedule | Runs |
72+| --- | --- |
73+| `"0 9 * * mon"` | Mondays at 09:00 UTC |
74+| `"*/30 * * * *"` | Every half hour |
75+| `"0 0 1 * *"` | At midnight on the first of each month |
76+| `"0 17 * * mon-fri"` | Weekdays at 17:00 UTC |
77+
78+A scheduled run is not about any issue or pull request, so it can only use
79+`open_issue` and `notify`.
80+
81+## Conditions: `if`
82+
83+`if` maps fields to the values they must have. Give one value or a list:
84+any value in the list matches. Every field must match. Matching ignores
85+case.
86+
87+```yaml
88+if:
89+ labels: [bug, regression] # has either label
90+ status: failed # checks.completed's data.status
91+ actor: ada # caused by ada
92+```
93+
94+| Field | Matches |
95+| --- | --- |
96+| `labels` | The issue has any of these labels. For a pull request, the labels of its issue. |
97+| `actor` | The username of who caused the event. A g1t agent is `g1t-agent`. |
98+| `branch` | The branch pushed to, for `git.push`. |
99+| Any field of the event's `data` | Such as `status` or `verdict`. Write `data.status` to be explicit. |
100+
101+When the conditions do not match, the run is recorded as skipped, with the
102+reason, such as *not labelled bug*.
103+
104+## Steps: `do`
105+
106+Steps run in order. When a step fails, the steps after it do not run, and
107+the run shows which step failed and why.
108+
109+| Step | Does |
110+| --- | --- |
111+| `comment: text` | Comments on the issue or pull request. |
112+| `label: name` | Adds a label to the issue. |
113+| `unlabel: name` | Removes a label from the issue. |
114+| `assign_agent` | Puts a g1t agent on the issue, which opens a pull request. |
115+| `message_agent: text` | Tells the agent working on the pull request. It reads the message at its next step. |
116+| `close_issue` | Closes the issue as completed. `close_issue: not_planned` closes it as not planned. |
117+| `reopen_issue` | Reopens the issue. |
118+| `open_issue:` | Opens a new issue: `title`, and optionally `body`, `labels` and `assign_agent: true`. |
119+| `notify:` | Posts `text` to an HTTPS `url`, such as a Slack or Discord incoming webhook. |
120+
121+A step without arguments is written as its name alone, such as
122+`- assign_agent`. A step that takes text is written as the name and the
123+text, such as `- label: triaged`. A step that takes several arguments takes
124+a mapping:
125+
126+```yaml
127+do:
128+ - open_issue:
129+ title: Weekly tidy-up
130+ body: Update dependencies that have new patch releases.
131+ labels: [chore]
132+ assign_agent: true
133+ - notify:
134+ url: https://hooks.slack.com/services/T000/B000/XXXX
135+ text: "Opened #{{opened}} in {{repo}}"
136+```
137+
138+`notify` sends `{"text": …, "content": …}`, the shape that Slack's,
139+Discord's and most chat tools' incoming webhooks take. It posts only to
140+public addresses.
141+
142+## Filling in text: `{{ }}`
143+
144+Text in steps can use these, written in double braces:
145+
146+| Name | Is |
147+| --- | --- |
148+| `{{repo}}` | The repository, such as `acme/web`. |
149+| `{{event}}` | What started the run, such as `issue.opened`, `schedule` or `manual`. |
150+| `{{automation}}` | The automation's name. |
151+| `{{actor}}` | The username of who caused the event. |
152+| `{{number}}`, `{{title}}`, `{{url}}` | The issue or pull request the event is about. |
153+| `{{branch}}` | The branch pushed to, for `git.push`. |
154+| `{{opened}}` | The number of the issue that `open_issue` just opened. |
155+| `{{data.field}}` | Any field of the event's data, such as `{{data.status}}`. |
156+
157+A name with no value is left empty.
158+
159+## Who it acts as
160+
161+An automation acts as its workspace. A comment from one shows the
162+workspace as its author and ends with the automation's name. An agent
163+it starts is billed to the workspace like any other run, through the
164+workspace's [model providers](/guides/models/).
165+
166+## The rules every run keeps
167+
168+- **Once per event.** An event runs each automation at most once, even if
169+ it is delivered again.
170+- **No loops.** An automation does not answer an event that its own run
171+ caused on the same issue or pull request in the last 10 minutes. An
172+ automation that labels issues on `issue.updated` does not keep running
173+ because it labelled one.
174+- **A limit per hour.** An automation makes at most 30 runs an hour.
175+ Runs past the limit are skipped and recorded. Change the limit, up to
176+ 200, with:
177+
178+ ```yaml
179+ limits:
180+ per_hour: 100
181+ ```
182+
183+## More examples
184+
185+Tell the agent when checks fail:
186+
187+```yaml
188+name: Tell the agent when checks fail
189+on: checks.completed
190+if:
191+ status: failed
192+do:
193+ - message_agent: "The acceptance checks failed. Read their output on #{{number}} and fix the cause."
194+```
195+
196+Announce merges in chat:
197+
198+```yaml
199+name: Announce merges
200+on: pull.merged
201+do:
202+ - notify:
203+ url: https://hooks.slack.com/services/T000/B000/XXXX
204+ text: "Merged into {{repo}}: {{title}} {{url}}"
205+```
206+
207+Close questions nobody followed up:
208+
209+```yaml
210+name: Close answered questions
211+on: manual
212+if:
213+ labels: question
214+do:
215+ - comment: "Closing this as answered. Reopen it if there is more to ask."
216+ - close_issue: not_planned
217+```
218+
219+## From the API
220+
221+| Tool | Route |
222+| --- | --- |
223+| `list_automations` | `GET /repos/{owner}/{name}/automations` |
224+| `list_automation_runs` | `GET /repos/{owner}/{name}/automations/runs`, optionally `?automation={id}` |
225+| `run_automation` | `POST /repos/{owner}/{name}/automations/{id}/runs`, optionally with `number` |
226+| `update_automation` | `PATCH /repos/{owner}/{name}/automations/{id}` with `enabled` |
227+
228+Running an automation or turning one on or off needs a member of the
229+workspace. Agents cannot run or change automations. To add or change one,
230+commit its file.
231+
232+```sh
233+curl -X POST https://api.g1t.sh/repos/acme/web/automations/aut_01m4…/runs \
234+ -H "Authorization: Bearer $G1T_TOKEN" -H "Content-Type: application/json" \
235+ -d '{"number": 42}'
236+```
+1−0
4848 <li><a href="/guides/integrations/">Integrations: Sentry, Jira, Linear</a></li>
4949 <li><a href="/guides/models/">Model providers: Anthropic, OpenAI, Gemini</a></li>
5050 <li><a href="/guides/webhooks/">Webhooks</a></li>
51+ <li><a href="/guides/automations/">Automations</a></li>
5152 </ul>
5253 </div>
5354 <div>
+11−0
132132
133133 Each has a workspace route too, under `/workspaces/{workspace}/hooks`.
134134
135+## Automations
136+
137+See [Automations](/guides/automations/). An automation is a file in `.g1t/automations/` on the default branch: to add or change one, commit it.
138+
139+| Tool | Required | What it does | Route |
140+| --- | --- | --- | --- |
141+| `list_automations` | `repo` | The automations: what starts each, its conditions and steps, whether it is on, any problem with its file, and its last run. | `GET /repos/{owner}/{name}/automations` |
142+| `list_automation_runs` | `repo` | The latest runs, newest first, with each step's result or why the run was skipped. `automation` for one automation's. | `GET /repos/{owner}/{name}/automations/runs` |
143+| `run_automation` | `repo`, `id` | Run it now, on issue or pull request `number` if given. Members only. | `POST /repos/{owner}/{name}/automations/{id}/runs` |
144+| `update_automation` | `repo`, `id`, `enabled` | Turn it on or off without changing its file. Members only. | `PATCH /repos/{owner}/{name}/automations/{id}` |
145+
135146 ## Messages
136147
137148 | Tool | Required | What it does | Route |
+13−1
192192 `disconnect_integration`, `get_model_routes`, `set_model_routes`,
193193 `get_context`, `import_issue`, `list_webhooks`, `create_webhook`,
194194 `update_webhook`, `delete_webhook`, `ping_webhook`,
195−`list_webhook_deliveries`, `redeliver_webhook`,
195+`list_webhook_deliveries`, `redeliver_webhook`, `list_automations`,
196+`list_automation_runs`, `run_automation`, `update_automation`,
196197 `list_repos`, `get_repo`, `create_repo`, `update_repo`,
197198 `get_repo_settings`, `update_repo_settings`, `list_events`,
198199 `create_workspace`, and `whoami`. MCP tools take the repository as `repo`,
227228 (HMAC-SHA256 of the body), retried for about seven hours. Deliveries,
228229 with request and response, are at `…/hooks/{id}/deliveries`.
229230
231+## Automations
232+
233+A YAML file in `.g1t/automations/` on the default branch is a rule: `on`
234+(an event such as `issue.opened`, `schedule: "0 9 * * mon"`, or `manual`),
235+optional `if` (`labels`, `actor`, `branch`, or an event data field), and
236+`do` steps: `comment`, `label`, `unlabel`, `assign_agent`, `message_agent`,
237+`open_issue`, `close_issue`, `reopen_issue`, `notify`. Text takes
238+`{{repo}}`, `{{number}}`, `{{title}}`, `{{url}}`, `{{actor}}`. Runs are at
239+`GET {repo}/automations/runs`; `POST {repo}/automations/{id}/runs` runs one.
240+
230241 ## Facts
231242
232243 - API base: `https://api.g1t.sh`. `GET /` lists every URL as a template.
264275 - [Integrations](https://docs.g1t.sh/guides/integrations/)
265276 - [Model providers](https://docs.g1t.sh/guides/models/)
266277 - [Webhooks](https://docs.g1t.sh/guides/webhooks/)
278+- [Automations](https://docs.g1t.sh/guides/automations/)
267279 - [Usage and billing](https://docs.g1t.sh/guides/usage-and-billing/)
268280 - [Git](https://docs.g1t.sh/guides/git/)
269281 - [MCP tools](https://docs.g1t.sh/reference/mcp/)