Pipeline policies
These are the built-in policies the office runs, in evaluation order (decision 0018). Each is a module in packages/office/src/pipeline/policies/, and this page is generated from them. Every policy that listens to an event receives it and proposes; the aggregation layer turns the proposals into the decisions. What outstaff does on its own explains the events and the decisions, and Writing a policy how to add a policy of your own.
A team changes a policy under pipeline.policies.<id> in team.yaml: enabled: false turns it off (it stays in the trace), instruction replaces the instruction of a wake or the note of an act, and when narrows it, so both its own condition and the team’s must hold. Policies of the team’s own, under policies.custom, run after these.
Overview
Section titled “Overview”| Policy | Listens to | Decides |
|---|---|---|
chat_to_addressed |
chat.message |
wake addressed (kind chat) |
review_to_author |
pr.review_submitted, pr.comment |
wake author (kind review_feedback) |
merged_feedback_to_author |
pr.review_submitted, pr.comment |
wake author (kind merged_feedback) |
merged_closes_ticket |
pr.merge_checks_passed |
act for author, else assignee, else last_worker: move the ticket to done, assign it to the agent acted for |
merge_checks_failed_to_agent |
pr.merge_checks_failed |
wake author, else assignee, else last_worker (kind merge_checks_failed) |
rebase_to_author |
pr.conflicted, pr.behind_base, pr.base_merged |
wake author (kind rebase) |
ci_failed_to_author |
pr.ci_failed |
wake author (kind ci_failed) |
merge_ready |
pr.review_submitted, pr.ci_passed, pr.base_merged |
wake author (kind merge) with the merge context, when its checks are green and the repository is in policies.merge.repos |
opened_to_review |
pr.opened |
act for author, else assignee, else last_worker: move the ticket to review |
link_pr_on_ticket |
pr.opened, pr.linked |
act for author: link the pull request on the ticket, when the tracker can link pull requests (tracker.development) |
assigned_to_assignee |
ticket.assigned, ticket.created |
wake assignee (kind assigned) |
ticket_comment_to_agent |
ticket.commented |
wake assignee (kind ticket_comment) |
ticket_comment_to_mentioned_agent |
ticket.commented |
wake mentioned (kind asked) |
ticket_comment_to_blocked_agent |
ticket.commented |
wake blocked_agent (kind ticket_comment) |
ticket_comment_to_last_worker |
ticket.commented |
wake last_worker (kind ticket_comment) |
moved_active_to_assignee |
ticket.moved |
wake assignee (kind assigned) |
moved_active_to_last_worker |
ticket.moved |
act for last_worker: assign it to the agent acted for, then wake them (kind assigned) |
closed_stops_work |
ticket.closed |
stop the work on the ticket of every agent but the one who closed it; a ticket closed as done by an unknown closer or an automation stops nothing |
subticket_closed_to_agent |
ticket.closed |
wake assignee, else last_worker, else the parent’s agent (kind assigned) on the ticket’s parent, the first of them with more unfinished sub-tickets of the parent |
subtickets_closed_move_parent |
ticket.closed |
act for the parent’s agent: move the parent to done and assign it to the agent, when its own pull requests merged, else to review and assign it to the requester; when the closed ticket was its last open sub-ticket |
subtickets_closed_close_parent |
ticket.closed |
act for the parent’s agent (the one it is assigned to, else the one that last worked it, else the closed sub-ticket’s): move the parent to done and assign it to the agent, when it has no open pull request of its own, else to review and assign it to the requester; when the closed ticket was its last open sub-ticket |
subtickets_in_review_move_parent |
ticket.moved, ticket.closed |
act for the parent’s agent (the one it is assigned to, else the one that last worked it, else the sub-ticket’s): move the parent to review and assign it to the requester; when every sub-ticket is done, canceled or in review, at least one in review, and no open pull request of its own is a draft |
milestone_done_to_pm |
ticket.closed |
wake the PM (role:pm, kind milestone) on the closed ticket, when every other ticket of its milestone the office knows is done or canceled |
unblocked_to_blocked_agent |
ticket.unblocked |
wake blocked_agent (kind unblocked) |
unblocked_to_ready |
ticket.unblocked |
act for assignee: move the ticket to ready, then wake them (kind assigned), unless the blocker is a sub-ticket of the same parent and the parent is with that agent (parentAgent): then only move it; with no agent assigned, act for closer: move the ticket to ready |
doc_comment_to_agent |
doc.commented |
wake mentioned, else doc_author (kind doc_feedback) |
doc_comment_to_mentioned_agent |
doc.commented |
wake mentioned (kind doc_feedback) |
link_doc_on_ticket |
doc.linked |
act for doc_author, else actor: link the document on the ticket, when the knowledge base can link documents on tickets (knowledge.issueLinks) |
start_marks_active |
agent.started |
act for actor: assign it to the agent acted for, move the ticket to active |
hand_back_done |
agent.handed_back |
act for actor: move the ticket to review, assign it to the requester, unless the agent handed the ticket over to someone else; a ticket with open sub-tickets stays active with the agent instead, unless every sub-ticket is in review or closed; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester |
hand_back_silent_restores |
agent.handed_back |
act for the agent: move the ticket back to the status it had before the round, and assign it back to whom it had, for each of the two still as the round’s start set it; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester |
hand_back_blocked |
agent.handed_back |
act for actor: move the ticket to blocked, assign it to the requester, when no PM unblocks it, unless the agent handed the ticket over to someone else; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester |
hand_back_blocked_to_pm |
agent.handed_back |
act for actor: move the ticket to blocked, assign it to role:pm; then wake role:pm (kind unblock), when the PM is not the blocked agent, unless the agent handed the ticket over to someone else; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester |
notify_human_on_handoff |
agent.handed_back, ticket.assigned, pr.opened |
notify the human in chat, as the agent: the requester on a hand-back as done (or the human the agent handed the ticket over to; nothing more when the work came from a chat thread, which gets the result), with every other ticket of the item the hand-back gives the requester for review, the assignee when an agent gives a ticket in review or blocked to a human (not the echo of an office act, nor the agent blocked on it), the requester of the ticket of an agent’s pull request opened for review; on policies.notify_handoff |
idle_pulls_next |
agent.idle |
wake actor (kind assigned), with its next ready ticket (for a sub-ticket, on its parent) |
Policies
Section titled “Policies”chat_to_addressed
Section titled “chat_to_addressed”A chat message wakes the agent it was written to.
Listens to chat.message. Decides: wake addressed (kind chat).
When:
actor_kind: human
Instruction:
{{actor.id}} wrote to you in chat. Answer in the thread. If they ask for work, decide how it fits your queue.review_to_author
Section titled “review_to_author”A human’s review or comment on an agent’s open pull request wakes its author.
Listens to pr.review_submitted, pr.comment. Decides: wake author (kind review_feedback).
When:
- all of:
actor_kind: humanpr_author_kind: agentpr_open: true- not:
- all of:
review_state: approvedhas_body: false
- all of:
Instruction:
{{actor.id}} left feedback on your pull request #{{pr.number}} ({{pr.title}}). Address each point, answer in its thread and push.merged_feedback_to_author
Section titled “merged_feedback_to_author”A human’s review or comment on an agent’s merged pull request wakes its author.
Listens to pr.review_submitted, pr.comment. Decides: wake author (kind merged_feedback).
When:
- all of:
actor_kind: humanpr_author_kind: agentpr_merged: true- not:
- all of:
review_state: approvedhas_body: false
- all of:
Instruction:
{{actor.id}} commented on your merged pull request #{{pr.number}} ({{pr.title}}). Answer there. If they ask for a change, open a follow-up pull request.merged_closes_ticket
Section titled “merged_closes_ticket”A merge into the default branch closes the ticket once the checks on its merge commit pass (or none start), unless another of its pull requests or one of its sub-tickets is open; the ticket ends with the agent who did the work: for the author, or, for a human’s pull request, the agent the ticket is assigned to, else the agent who last worked on it.
Listens to pr.merge_checks_passed. Decides: act for author, else assignee, else last_worker: move the ticket to done, assign it to the agent acted for.
When:
- all of:
ticket_status: backlog, ready, active, review, blockedpr_base_default: true- not:
ticket_prs_open: true
- not:
open_subtickets: true
Note posted with the change:
Moved to done: pull request #{{pr.number}} by {{pr.author}} merged and the checks on its merge commit passed.merge_checks_failed_to_agent
Section titled “merge_checks_failed_to_agent”A check that fails on the merge commit of a pull request in the default branch, such as a deploy, wakes the ticket’s agent with the failed step’s log: the pull request’s author, or, for a human’s pull request, the agent the ticket is assigned to, else the agent who last worked on it. The ticket stays open.
Listens to pr.merge_checks_failed. Decides: wake author, else assignee, else last_worker (kind merge_checks_failed).
When:
- all of:
pr_merged: true- not:
ticket_status: canceled
Instruction:
Pull request #{{pr.number}} ({{pr.title}}) by {{pr.author}} merged, but checks on its merge commit failed: {{checks}}. The end of the failed step's log is in the context; `ost ci log <check link>` reads more. Fix it the way the repository asks, for example with a follow-up pull request on the same ticket. The ticket stays open until a merge for it passes its checks.rebase_to_author
Section titled “rebase_to_author”An agent’s open pull request that conflicts, is behind its base, or whose base merged wakes its author, naming the merge that caused it.
Listens to pr.conflicted, pr.behind_base, pr.base_merged. Decides: wake author (kind rebase).
When:
- all of:
pr_author_kind: agentpr_open: true- not:
ticket_status: canceled
Instruction:
Your pull request #{{pr.number}} ({{pr.title}}) {{pr.problem}}{{cause}}. Bring it up to date with `{{pr.base}}` the way the repository asks, and push. Then keep the pull request description current; if the approach changed, comment with what changed and why.ci_failed_to_author
Section titled “ci_failed_to_author”Failing checks on an agent’s open pull request wake its author.
Listens to pr.ci_failed. Decides: wake author (kind ci_failed).
When:
- all of:
pr_author_kind: agentpr_open: true- not:
ticket_status: canceled
Instruction:
Your pull request #{{pr.number}} ({{pr.title}}) {{pr.problem}}. The failing checks are in the feedback. Fix them and push.merge_ready
Section titled “merge_ready”An agent’s approved pull request that may be ready to merge wakes its author to decide (policies.merge.on_approval): an allowed approver approves it with its checks green, its checks turn green, or the pull request it was stacked on merges. Not while an allowed approver’s request for changes is outstanding.
Listens to pr.review_submitted, pr.ci_passed, pr.base_merged. Decides: wake author (kind merge) with the merge context, when its checks are green and the repository is in policies.merge.repos.
On only while policies.merge.on_approval is on.
When:
- all of:
- all of:
pr_author_kind: agentpr_open: true- not:
ticket_status: canceled
pr_draft: falsepr_approved: true
- all of:
Instruction:
#{{pr.number}} ({{pr.title}}) is approved and may be ready to merge. Decide whether to merge it now, wait, or coordinate first; follow the repository's instructions on merging.opened_to_review
Section titled “opened_to_review”A pull request opened for review moves its ticket to review: for the author, or, for a human’s pull request, the agent the ticket is assigned to, else the agent who last worked on it. A ticket with open sub-tickets stays active until the last one closes.
Listens to pr.opened. Decides: act for author, else assignee, else last_worker: move the ticket to review.
When:
- all of:
- not:
pr_draft: true
ticket_status: backlog, ready, active- not:
open_subtickets: true
- not:
Note posted with the change:
Moved to review: pull request #{{pr.number}} by {{pr.author}} is open for review.link_pr_on_ticket
Section titled “link_pr_on_ticket”An agent’s pull request opened for a ticket, or linked to one after it was opened, is shown on the ticket in the tracker (its development section), by the author with its own tracker account. Bookkeeping: it wakes no one.
Listens to pr.opened, pr.linked. Decides: act for author: link the pull request on the ticket, when the tracker can link pull requests (tracker.development).
When: always.
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.link_pr_on_ticket.instruction.
assigned_to_assignee
Section titled “assigned_to_assignee”A ticket assigned to an agent, by anyone but that agent, wakes the agent.
Listens to ticket.assigned, ticket.created. Decides: wake assignee (kind assigned).
When:
- all of:
assignee_kind: agent- not:
actor_kind: automation
- not:
actor_is: assignee
- not:
ticket_status: done, canceled
Instruction:
{{ticket}} is assigned to you. Work on it the way the repository asks.ticket_comment_to_agent
Section titled “ticket_comment_to_agent”A human’s comment, mentioning no agent, on a ticket assigned to an agent wakes that agent.
Listens to ticket.commented. Decides: wake assignee (kind ticket_comment).
When:
- all of:
actor_kind: human- not:
ticket_status: done, canceled
- not:
agent_mentioned: true
assignee_kind: agent
Instruction:
{{actor.id}} commented on {{ticket}}. Read the comment and act on it.ticket_comment_to_mentioned_agent
Section titled “ticket_comment_to_mentioned_agent”A comment on a ticket, by a human or another agent, wakes the agent it mentions first, to answer or act on it; the ticket stays with its assignee. An agent’s comment that mentions no other agent wakes no one.
Listens to ticket.commented. Decides: wake mentioned (kind asked).
When:
- all of:
- not:
actor_kind: automation
- not:
ticket_status: done, canceled
agent_mentioned: true
- not:
Instruction:
{{actor.id}} mentioned you in a comment on {{ticket}}. Read the comment and judge first whether anything in it is for you: a question you can answer, or an action that is yours. If something is, answer it, or do what it asks, on the ticket, once. If nothing is, end the round silently: no comment and no message; finish with `ost handback silent` and a one-line journal note. Never restate what someone else already said or asked. The ticket stays with its assignee: leave its assignee and status as they are, unless the comment asks you to take the ticket over.ticket_comment_to_blocked_agent
Section titled “ticket_comment_to_blocked_agent”A comment on a blocked ticket, by a human or an agent other than the agent blocked on it, wakes the agent blocked on it; unless the ticket is with an agent (who is unblocking it), the comment mentions an agent (that agent is woken), or an agent comments during its own round on the ticket.
Listens to ticket.commented. Decides: wake blocked_agent (kind ticket_comment).
When:
- all of:
blocked_agent: true- not:
actor_kind: automation
- not:
actor_is: blocked_agent
- not:
assignee_kind: agent
- not:
agent_mentioned: true
- not:
actor_in_round: true
Instruction:
{{actor.id}} commented on {{ticket}}, which you handed back as blocked. Read the comment. If it unblocks the work, assign the ticket to yourself, move it to active and continue. Otherwise answer on the ticket what is still missing.ticket_comment_to_last_worker
Section titled “ticket_comment_to_last_worker”A human’s comment, mentioning no agent, on a ticket handed back to a human (in review, or blocked with no agent blocked on it) wakes the agent who last worked on it.
Listens to ticket.commented. Decides: wake last_worker (kind ticket_comment).
When:
- all of:
actor_kind: human- not:
agent_mentioned: true
assignee_kind: humanticket_status: review, blocked- not:
blocked_agent: true
Instruction:
{{actor.id}} commented on {{ticket}}, which you handed back. Answer the comment on the ticket. If it needs more work, assign the ticket to yourself, move it to active and do the work.moved_active_to_assignee
Section titled “moved_active_to_assignee”A human moving a ticket to active wakes the agent assigned.
Listens to ticket.moved. Decides: wake assignee (kind assigned).
When:
- all of:
actor_kind: humanmoved_to: activeassignee_kind: agent
Instruction:
{{actor.id}} moved {{ticket}} to active. Pick the work up.moved_active_to_last_worker
Section titled “moved_active_to_last_worker”A human moving a ticket assigned to a human to active, without the needs-human label, gives it back to the agent who last worked on it and wakes them.
Listens to ticket.moved. Decides: act for last_worker: assign it to the agent acted for, then wake them (kind assigned).
When:
- all of:
actor_kind: humanmoved_to: activeassignee_kind: human- not:
has_label: $needs_human
Instruction:
{{actor.id}} moved {{ticket}} to active and it is assigned to you again. Pick the work up.Note posted with the change: none; the instruction is the wake’s.
closed_stops_work
Section titled “closed_stops_work”A ticket canceled, or closed as done by someone other than the agent working on it, stops the work on it: every agent’s queued work on it and its pull requests is canceled, and an agent running such work is told to stop when its round ends. The agent who closed the ticket is left alone.
Listens to ticket.closed. Decides: stop the work on the ticket of every agent but the one who closed it; a ticket closed as done by an unknown closer or an automation stops nothing.
When:
ticket_status: done, canceled
Note posted with the change:
{{ticket}} was {{closed}} by {{closer}} at {{closed.at}}. Stop, and don't open a pull request for it. If the work belongs to another ticket, say which and hand back.subticket_closed_to_agent
Section titled “subticket_closed_to_agent”A sub-ticket closing wakes an agent on the parent ticket when the parent is open and that agent has more unfinished sub-tickets of it: the closed sub-ticket’s agent, else the parent’s. The agent planned their order when it split the parent, and picks the next one.
Listens to ticket.closed. Decides: wake assignee, else last_worker, else the parent’s agent (kind assigned) on the ticket’s parent, the first of them with more unfinished sub-tickets of the parent.
When:
- all of:
ticket_status: done, canceledparent_status: backlog, ready, active, review, blocked
Instruction:
{{ticket}} was {{closed}}. The open sub-tickets of {{parent}}: {{parent.open}}. Continue with the next one in the order you planned, the way the repository asks. When none is for you to do now (it waits on a human's review, or on a sub-ticket someone else has), you are waiting, not blocked: hand back silent, with no new message.subtickets_closed_move_parent
Section titled “subtickets_closed_move_parent”The last open sub-ticket of an active parent closing moves the parent on, for its agent: to done, with the agent, when the parent’s own pull requests merged; otherwise to review, with the requester.
Listens to ticket.closed. Decides: act for the parent’s agent: move the parent to done and assign it to the agent, when its own pull requests merged, else to review and assign it to the requester; when the closed ticket was its last open sub-ticket.
When:
- all of:
ticket_status: done, canceledparent_status: active
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.subtickets_closed_move_parent.instruction.
subtickets_closed_close_parent
Section titled “subtickets_closed_close_parent”The last open sub-ticket of a parent in review or blocked closing closes the parent, for the agent that last worked it, with a note listing the closed sub-tickets: to done, with the agent, when the parent has no open pull request of its own; otherwise to review, with the requester. A parent canceled or done is left alone.
Listens to ticket.closed. Decides: act for the parent’s agent (the one it is assigned to, else the one that last worked it, else the closed sub-ticket’s): move the parent to done and assign it to the agent, when it has no open pull request of its own, else to review and assign it to the requester; when the closed ticket was its last open sub-ticket.
When:
- all of:
ticket_status: done, canceledparent_status: review, blocked
Note posted with the change:
{{ticket}} was the last open sub-ticket of {{parent}}. Its closed sub-tickets: {{parent.closed}}.subtickets_in_review_move_parent
Section titled “subtickets_in_review_move_parent”A sub-ticket moving to review, or closing, moves an active parent to review and gives it to the requester, for the parent’s agent, once every sub-ticket of it is done, canceled or in review, with at least one in review. A parent’s own open pull request counts only once it is open for review, not a draft. When every sub-ticket closed, subtickets_closed_move_parent moves it instead.
Listens to ticket.moved, ticket.closed. Decides: act for the parent’s agent (the one it is assigned to, else the one that last worked it, else the sub-ticket’s): move the parent to review and assign it to the requester; when every sub-ticket is done, canceled or in review, at least one in review, and no open pull request of its own is a draft.
When:
- all of:
- any of:
moved_to: reviewticket_status: done, canceled
parent_status: ready, active
- any of:
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.subtickets_in_review_move_parent.instruction.
milestone_done_to_pm
Section titled “milestone_done_to_pm”The last unfinished ticket of a milestone (a tracker initiative) closing wakes the team’s PM, to close the milestone, propose the next one and ask a trusted human to confirm it. The office counts the milestone’s tickets it knows; the PM checks the milestone in the tracker first.
Listens to ticket.closed. Decides: wake the PM (role:pm, kind milestone) on the closed ticket, when every other ticket of its milestone the office knows is done or canceled.
When:
- all of:
ticket_status: done, canceledin_milestone: true
Instruction:
{{ticket}} was {{closed}}, and it was the last open ticket of milestone "{{milestone}}" ({{milestone.id}}) that the office knows. Check with `ost milestone show {{milestone.id}}` that nothing in it is left. If it is finished, close it (`ost milestone status {{milestone.id}} done`), update the roadmap, propose the next milestone with what it will deliver, and ask a trusted human to confirm it. File its tickets only once they confirm.unblocked_to_blocked_agent
Section titled “unblocked_to_blocked_agent”A blocked ticket whose last open blocker was closed wakes the agent blocked on it, to check whether it can go on; the ticket stays where it is, since it may be blocked for other reasons too.
Listens to ticket.unblocked. Decides: wake blocked_agent (kind unblocked).
When:
blocked_agent: true
Instruction:
{{blocker}}, which blocked {{ticket}}, is closed, and no other ticket blocks it. You handed {{ticket}} back as blocked: check whether you can continue now. If so, assign it to yourself, move it to active and continue. Otherwise answer on the ticket what is still missing.unblocked_to_ready
Section titled “unblocked_to_ready”A blocked ticket whose last open blocker was closed, with no agent blocked on it, was only waiting on its blockers: it moves to ready, for the agent it is assigned to, who is then woken; else for the agent who closed the blocker. When the blocker is a sub-ticket of the same parent and that parent is with the same agent, the ticket is only moved and no one is woken here: the agent holding the parent coordinates its sub-tickets, and the idle pull starts this one when it has nothing queued.
Listens to ticket.unblocked. Decides: act for assignee: move the ticket to ready, then wake them (kind assigned), unless the blocker is a sub-ticket of the same parent and the parent is with that agent (parentAgent): then only move it; with no agent assigned, act for closer: move the ticket to ready.
When:
- all of:
ticket_status: blocked- not:
blocked_agent: true
Instruction:
{{blocker}}, which blocked {{ticket}}, is closed, and no other ticket blocks it: {{ticket}} is ready again. Work on it the way the repository asks.Note posted with the change: none; the instruction is the wake’s.
doc_comment_to_agent
Section titled “doc_comment_to_agent”A human’s comment on a document wakes the agent it mentions, else the agent who wrote it.
Listens to doc.commented. Decides: wake mentioned, else doc_author (kind doc_feedback).
When:
actor_kind: human
Instruction:
{{actor.id}} commented on the document {{doc.title}}. Answer in the document and change it if needed.doc_comment_to_mentioned_agent
Section titled “doc_comment_to_mentioned_agent”An agent’s comment on a document wakes the other agent it mentions. An agent’s comment that mentions no other agent wakes no one.
Listens to doc.commented. Decides: wake mentioned (kind doc_feedback).
When:
- all of:
actor_kind: agentagent_mentioned: true
Instruction:
{{actor.id}} mentioned you in a comment on the document {{doc.title}}. Answer in the document and change it if needed.link_doc_on_ticket
Section titled “link_doc_on_ticket”A document an agent wrote for a ticket, in a round on the ticket or attached to it later, is shown on the ticket in the tracker, by its author with its own account. Bookkeeping: it wakes no one.
Listens to doc.linked. Decides: act for doc_author, else actor: link the document on the ticket, when the knowledge base can link documents on tickets (knowledge.issueLinks).
When: always.
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.link_doc_on_ticket.instruction.
start_marks_active
Section titled “start_marks_active”A round of work starting on a ticket assigns the ticket to the agent and moves it to active, for the agent.
Listens to agent.started. Decides: act for actor: assign it to the agent acted for, move the ticket to active.
When:
- all of:
work_kind: assigned, review_feedback, ticket_comment, rebase, ci_failed, merge_checks_failed- not:
ticket_status: done, canceled
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.start_marks_active.instruction.
hand_back_done
Section titled “hand_back_done”A hand-back as done moves the ticket to review and gives it to the requester, for the agent, unless the agent handed the ticket over to someone else during the work; a ticket with open sub-tickets stays active with the agent instead, unless every sub-ticket is in review or closed. The work item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) go to review and to the requester too. A merge round’s hand-back leaves the ticket as it is: nothing in it is left for the human.
Listens to agent.handed_back. Decides: act for actor: move the ticket to review, assign it to the requester, unless the agent handed the ticket over to someone else; a ticket with open sub-tickets stays active with the agent instead, unless every sub-ticket is in review or closed; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester.
When:
- all of:
hand_back_status: done- not:
work_kind: merge
- not:
ticket_status: blocked, done, canceled
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.hand_back_done.instruction.
hand_back_silent_restores
Section titled “hand_back_silent_restores”A silent hand-back leaves the ticket as it was before the round: what the round’s start changed (the move to active, the assignment to the agent) is undone, for the agent. A field someone changed since is left alone, and so is a parent the agent kept active for its open sub-tickets. The work item’s other tickets awaiting review go to review and to the requester too. A blocked hand-back the office found waiting on work in flight (the ticket’s pull requests open for review, its sub-tickets in review or with an agent) comes as silent, and its trace names that work: no PM is woken, and no human is told again.
Listens to agent.handed_back. Decides: act for the agent: move the ticket back to the status it had before the round, and assign it back to whom it had, for each of the two still as the round’s start set it; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester.
When:
- all of:
hand_back_status: silent- not:
ticket_status: done, canceled
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.hand_back_silent_restores.instruction.
hand_back_blocked
Section titled “hand_back_blocked”A hand-back as blocked, or as done on a ticket the agent moved to blocked, on a team with no PM to unblock it (none, or the PM is the blocked agent), moves the ticket to blocked and gives it to the requester, for the agent, unless the agent handed the ticket over to someone else during the work. The work item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) go to review and to the requester.
Listens to agent.handed_back. Decides: act for actor: move the ticket to blocked, assign it to the requester, when no PM unblocks it, unless the agent handed the ticket over to someone else; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester.
When:
- all of:
- any of:
hand_back_status: blocked- all of:
hand_back_status: doneticket_status: blocked
- not:
ticket_status: done, canceled
- any of:
Note posted with the change: none, since the ticket shows the change. A team can add one with pipeline.policies.hand_back_blocked.instruction.
hand_back_blocked_to_pm
Section titled “hand_back_blocked_to_pm”A hand-back as blocked, or as done on a ticket the agent moved to blocked, on a team with a PM other than the blocked agent, moves the ticket to blocked and gives it to the PM, for the agent, then wakes the PM to unblock it; unless the agent handed the ticket over to someone other than the PM during the work. The work item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) go to review and to the requester, not the PM.
Listens to agent.handed_back. Decides: act for actor: move the ticket to blocked, assign it to role:pm; then wake role:pm (kind unblock), when the PM is not the blocked agent, unless the agent handed the ticket over to someone else; the item’s other tickets awaiting review (the ones it created that are in review, and the ones whose pull request it opened) move to review and go to the requester.
When:
- all of:
- any of:
hand_back_status: blocked- all of:
hand_back_status: doneticket_status: blocked
- not:
ticket_status: done, canceled
- any of:
Instruction:
{{actor.id}} handed {{ticket}} back as blocked, and it is assigned to you to unblock. Try everything before involving a human: answer from what you know, find the information, or ask the right teammate with `ost ask`. When it is unblocked, comment the answer on the ticket and assign it back to {{actor.id}}. Only if a human is needed, assign it to the requester, {{requester}}, with a comment that says exactly what is needed. If all it waits on is a review the human already has (the ticket or its pull request is in review with them), nothing is blocked: leave it, send no new message, and hand back silent.Note posted with the change: none; the instruction is the wake’s.
notify_human_on_handoff
Section titled “notify_human_on_handoff”When work lands on a human, the agent tells them in a direct message in chat, with the ticket and pull request links and what is needed: a hand-back as done that gives the ticket to them, listing every ticket it gives them (the item’s sub-tickets in review and the tickets of the pull requests it opened too), a ticket in review or blocked that an agent gives to them (a PM that cannot unblock it, for example), or an agent’s pull request opened for review, for the requester of its ticket. The office batches one agent’s messages to one human.
Listens to agent.handed_back, ticket.assigned, pr.opened. Decides: notify the human in chat, as the agent: the requester on a hand-back as done (or the human the agent handed the ticket over to; nothing more when the work came from a chat thread, which gets the result), with every other ticket of the item the hand-back gives the requester for review, the assignee when an agent gives a ticket in review or blocked to a human (not the echo of an office act, nor the agent blocked on it), the requester of the ticket of an agent’s pull request opened for review; on policies.notify_handoff.
On only while policies.notify_handoff is on.
When:
- any of:
- all of:
hand_back_status: done- not:
ticket_status: blocked, done, canceled
- all of:
actor_kind: agentassignee_kind: humanticket_status: review, blocked
- all of:
pr_author_kind: agent- not:
pr_draft: true
- all of:
idle_pulls_next
Section titled “idle_pulls_next”An agent with nothing queued or running is woken with its next ready ticket: the highest tracker priority, then the one ready the longest (policies.pull_ready). For a sub-ticket of an open parent the agent is woken on the parent, so it takes the sub-tickets in the order it planned.
Listens to agent.idle. Decides: wake actor (kind assigned), with its next ready ticket (for a sub-ticket, on its parent).
On only while policies.pull_ready is on.
When: always.
Instruction:
You have nothing queued. Your next ready work is {{next.ticket}}. Work on it the way the repository asks.Events
Section titled “Events”Every event the pipeline decides on. A policy’s on lists some of them.
chat.messagepr.openedpr.review_submittedpr.commentpr.mergedpr.closedpr.conflictedpr.ci_failedpr.ci_passedpr.behind_basepr.base_mergedpr.linkedpr.merge_checks_passedpr.merge_checks_failedticket.commentedticket.assignedticket.movedticket.createdticket.unblockedticket.closeddoc.commenteddoc.linkedagent.startedagent.handed_backagent.idle
Instruction variables
Section titled “Instruction variables”An instruction or note may use these placeholders, written {{name}}. One the event does not have is empty, and an unknown name in pipeline.policies.<id>.instruction keeps the default instruction, with a warning in the office log.
ticketstatusactor.idactor.kindevent.typepr.numberpr.titlepr.urlpr.repopr.basepr.headpr.authorstackstack.countticket.prsticket.prs.countpersondoc.titlepr.problemcausecause.numbercause.titlenext.ticketrequesterblockercheckscloserclosedclosed.atparentparent.openparent.closedmilestonemilestone.id