[{"data":1,"prerenderedAt":47},["ShallowReactive",2],{"$fohslf8v0goga":3},{"href":4,"title":5,"description":6,"kind":7,"mark":7,"planned":8,"contributors":9,"provenance":7,"express":8,"html":10,"headings":11},"\u002Fdocs\u002Fwork\u002Fwriting-a-task","Writing a clonable task","The rules for a task that works in an enterprise that is not its author's, each with the mistake it prevents, and a checklist to run before you publish one.",null,false,[],"\u003Cp>A task in the Catalog runs in enterprises its author has never seen. A \u003Ca href=\"\u002Fdocs\u002Fwork\u002Ftasks#clone-and-copy\">clone\u003C\u002Fa>\nkeeps the original's definition and cannot be edited, so whatever its author wrote into it, every clone runs as\nwritten. These rules are what a task needs to work there, whether a person or an agent writes it, and each one comes\nwith an example of the mistake it prevents. The \u003Ca href=\"\u002Fdocs\u002Fwork\u002Fwriting-a-task#checklist\">checklist\u003C\u002Fa> at the end is the\nsame rules as questions, for whoever reviews the task before it is published.\u003C\u002Fp>\n\u003Cp>This page is for anyone who writes a task to publish to the Catalog, and for whoever reviews one. It builds on the\nreference pages and does not repeat them: \u003Ca href=\"\u002Fdocs\u002Fwork\u002Ftasks\">Tasks\u003C\u002Fa> for what a task is made of and how to make one,\n\u003Ca href=\"\u002Fdocs\u002Fwork\u002Fhandoffs\">Handoffs\u003C\u002Fa> for outcomes and successors, \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fmemory\">Memory\u003C\u002Fa>,\n\u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fgates\">Gates and tool scopes\u003C\u002Fa>, and \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fspend\">Spend and models\u003C\u002Fa>. The full list of\noperations the OS gives a task, with the exact name of each, is \u003Ca href=\"\u002Fdocs\u002Ftools\u002Fbuilt-in\">Built-in tools\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"rules\">Rules\u003C\u002Fh2>\n\u003Cp>Nine rules, in the order a reviewer checks them.\u003C\u002Fp>\n\u003Ch3 id=\"name-no-enterprise-person-domain-repository-path-or-date\">Name no enterprise, person, domain, repository, path or date\u003C\u002Fh3>\n\u003Cp>A task names none of these: an enterprise, a person, a domain, a repository, a file path or a fixed date. Each is\ntrue in its author's enterprise and wrong in every clone. Write the part a thing plays instead: &quot;the repository in\nthe \u003Ccode>repo\u003C\u002Fcode> input&quot;, &quot;the person who approves releases&quot;, &quot;the day the run starts&quot;. Where the run needs the actual\nvalue, the next rule says where it comes from.\u003C\u002Fp>\n\u003Cp>This holds in every part a clone takes: the goal, the success metric, the guardrails, the skill, the inputs' labels\nand defaults, the values a tool is narrowed to, and the successors.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A release-notes task's skill says &quot;Read the pull requests merged in \u003Ccode>acme\u002Fweb\u003C\u002Fcode>, save the notes to\n\u003Ccode>\u002Fsrv\u002Facme\u002Fnotes\u002F\u003C\u002Fcode>, and send them to \u003Ccode>sam@acme.example\u003C\u002Fcode> before 1 March 2027.&quot; In a clone, every one of those is\nsomebody else's repository, folder, colleague and deadline.\u003C\u002Fp>\n\u003Ch3 id=\"read-what-varies-from-memory-or-an-input\">Read what varies from memory or an input\u003C\u002Fh3>\n\u003Cp>Whatever an enterprise must be able to change, the task reads when it runs. It is never written into the skill:\nwho approves, which repository, the voice it writes in, a threshold, a sign-off. There are two places for it:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>An input\u003C\u002Fstrong>, for what changes from run to run, or what whoever starts the run knows: the repository, the issue,\nthe customer. Give it a label that says what to put in, and a default only when any enterprise could use it. See\n\u003Ca href=\"\u002Fdocs\u002Fwork\u002Ftasks#inputs\">Inputs\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Memory\u003C\u002Fstrong>, for what the enterprise knows and keeps: its voice, its approvers, its working days. The skill asks\nfor it, and says what to do when memory has no answer yet. The next rule covers both.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>A clone cannot be edited, so a value written into the skill can only be changed by the task's author, in a new\nversion every clone would have to take.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A support-reply task's skill says &quot;Sign every reply 'The Acme team' and offer 10% off a late order.&quot;\nEvery enterprise that clones it signs as Acme and gives away a discount it never chose. The sign-off and the\ndiscount belong in each enterprise's own memory.\u003C\u002Fp>\n\u003Ch3 id=\"state-what-it-reads-from-memory-and-what-it-writes\">State what it reads from memory and what it writes\u003C\u002Fh3>\n\u003Cp>Each task says, in its skill, what it asks memory for and what it trains back, so a reviewer can see both without\nrunning it. A clone brings no memory with it, so the skill also says what a run does when \u003Ccode>memory.ask\u003C\u002Fcode> answers\n\u003Ccode>insufficient_evidence\u003C\u002Fcode>: every first run in a new enterprise does.\u003C\u002Fp>\n\u003Cp>What the task writes follows three rules:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Facts and outcomes only.\u003C\u002Fstrong> Train what the run established, or how the work ended: &quot;the customer accepted the\nrefund on the second reply&quot;. Never its reasoning, a draft, or what memory just told it.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>One note per outcome.\u003C\u002Fstrong> One claim, in a sentence that still means something to a run with none of this one's\ncontext. Two outcomes are two notes.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>A correction replaces the note it corrects.\u003C\u002Fstrong> When a note is wrong, train a correction that names the note it\nsupersedes, never a second note beside it.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>The task lists \u003Ccode>memory.ask\u003C\u002Fcode> and \u003Ccode>memory.train\u003C\u002Fcode> among its tools. A run writes only its own task's notes, and a clone\ndoes too. See \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fmemory#train\">Memory\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>Every run also consults memory before it starts and records what it learned when it finishes, without the task\nasking (see \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fmemory#before-and-after-every-run\">Before and after every run\u003C\u002Fa>). The skill does not\nrepeat those steps: what it states is the questions it asks with \u003Ccode>memory.ask\u003C\u002Fcode> and the notes it trains with\n\u003Ccode>memory.train\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A task that chases unpaid invoices trains &quot;Checked memory, found nothing, drafted a reminder, decided to\nwait, sent it Friday, customer paid Monday&quot; after a run. One note carries five claims and the run's reasoning, so a\nlater run asking when this customer pays reads a story, and the wrong half of it cannot be corrected alone.\u003C\u002Fp>\n\u003Ch3 id=\"put-a-gate-on-every-tool-that-acts-outside-the-os\">Put a gate on every tool that acts outside the OS\u003C\u002Fh3>\n\u003Cp>Every tool that sends, publishes, spends or changes something outside the OS has a gate: a mail, a post, a payment,\na comment, a merge, a record in another system. Reads need none. A gate on a \u003Ccode>workspace.*\u003C\u002Fcode> or \u003Ccode>memory.*\u003C\u002Fcode> tool is\nsaved but never waits: a workspace pushes only to a branch that is not the default one, and the gate that counts is\non the merge (see \u003Ca href=\"\u002Fdocs\u002Ftools\u002Fworkspaces#what-waits-for-you\">Workspaces\u003C\u002Fa>). A clone keeps the gates of the task it\nwas cloned from, and cannot change them, so a gate missing from the original is missing in every enterprise that\ntakes it. See \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fgates#a-task-created-without-gates\">Gates and tool scopes\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A task that answers customer mail holds \u003Ccode>os.mail_reply\u003C\u002Fcode> and was saved with \u003Ccode>gates: []\u003C\u002Fcode>, because its\nauthor had read every draft by hand for a month. In each clone, its first reply reaches a customer before anyone in\nthat enterprise has read a draft.\u003C\u002Fp>\n\u003Ch3 id=\"name-its-tools-exactly\">Name its tools exactly\u003C\u002Fh3>\n\u003Cp>List each tool the task calls by its exact name, \u003Ccode>github.add_issue_comment\u003C\u002Fcode> rather than \u003Ccode>github\u003C\u002Fcode>, and nothing it does\nnot call. In the portal's tool picker that is \u003Cstrong>Choose actions\u003C\u002Fstrong>, not \u003Cstrong>Add toolset\u003C\u002Fstrong>. Use the same names in the skill, so the model calls what the task holds: a run that calls a tool its task\ndoes not list fails. A whole vendor reaches every tool that vendor offers, the ones that write included, in every\nenterprise that connects it. \u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fgates#tool-scopes\">Tool scopes\u003C\u002Fa> says how to narrow a tool to some of its\nvalues.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A triage task lists \u003Ccode>github\u003C\u002Fcode> so that its skill can &quot;use GitHub as needed&quot;. That reaches\n\u003Ccode>github.merge_pull_request\u003C\u002Fcode> too, so the version is refused until it declares a merge gate, and once it does, every\nclone holds a merge the task never needed.\u003C\u002Fp>\n\u003Ch3 id=\"name-its-outcomes-and-where-each-leads\">Name its outcomes and where each leads\u003C\u002Fh3>\n\u003Cp>List every outcome the skill can end on, by the exact word it ends with, and the successor each one leads to, or\nthat it leads nowhere because the work is done. An outcome no rule routes is a dead end: the run stops there, and the\nwork is listed on \u003Cstrong>Blockers\u003C\u002Fstrong>. A clone looks for each successor by its slug in its own enterprise, and \u003Cstrong>Successors\u003C\u002Fstrong>\nnames it by that slug alone. So say which task each slug is in the skill, where it lists the outcomes it ends on:\nbeside each outcome, the successor's slug and one line on what that task does, such as &quot;\u003Ccode>needs_changes\u003C\u002Fcode> leads to\n\u003Ccode>fix-review-findings\u003C\u002Fcode>, a task that fixes what a review found&quot;. That is where a reviewer reads it, and where an\nenterprise that clones the task learns which task it needs under that slug. See\n\u003Ca href=\"\u002Fdocs\u002Fwork\u002Fhandoffs#named-outcomes\">Named outcomes\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A review task's skill ends \u003Ccode>{&quot;outcome&quot;:&quot;needs_review&quot;}\u003C\u002Fcode> when it is unsure, but its only successor rule\nis on \u003Ccode>needs_changes\u003C\u002Fcode>. Every unsure review stops as a dead end in every enterprise that cloned it, and nobody hears\nof it until someone reads \u003Cstrong>Blockers\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Ch3 id=\"state-its-finish\">State its finish\u003C\u002Fh3>\n\u003Cp>Say which outcomes finish the work, in \u003Cstrong>Finishes the work on\u003C\u002Fstrong> (\u003Ccode>finishesOn\u003C\u002Fcode>), and have the skill end on exactly\nthose words when the work is done. A task that can also stop without finishing, waiting on someone, ends on a\ndifferent outcome for that. See \u003Ca href=\"\u002Fdocs\u002Fwork\u002Fhandoffs#finished-work\">Finished work\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A task that closes resolved support tickets leaves \u003Cstrong>Finishes the work on\u003C\u002Fstrong> empty. Every ticket it\ncloses stays listed on \u003Cstrong>Waiting\u003C\u002Fstrong> in every clone, until someone there marks it finished by hand.\u003C\u002Fp>\n\u003Ch3 id=\"state-its-kpis\">State its KPIs\u003C\u002Fh3>\n\u003Cp>Say how anyone would know the task works: its success metric, as a number any enterprise that clones it can count,\nsuch as the share of replies sent within a working day, or of issues labelled without a person correcting the label.\nA metric only its author's enterprise can read, or a target set for its author's business, tells a clone nothing.\nWhere a run can count it, a KPI can name the task as its source, and once a person signs that KPI off, the task's runs\nrecord its readings with \u003Ccode>os.record_kpi_reading\u003C\u002Fcode>. See \u003Ca href=\"\u002Fdocs\u002Fcompany\u002Fteams\">Teams and charters\u003C\u002Fa> for how KPIs are\nkept.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> An onboarding task's success metric reads &quot;new starters are happy&quot;. No run can count that and no person\ncan record a reading of it, so nobody in a clone can tell a month it worked from a month it did not.\u003C\u002Fp>\n\u003Ch3 id=\"choose-a-model-tier-and-say-what-the-cheapest-cannot-do\">Choose a model tier, and say what the cheapest cannot do\u003C\u002Fh3>\n\u003Cp>Give the task a highest model tier, not an exact model. Each tier stands for a model on every provider, while an\nexact model may not be one the cloning enterprise's connection offers, and the run then uses the closest one it\ndoes. Start at \u003Ccode>economical\u003C\u002Fcode>, the cheapest. Choose \u003Ccode>mid\u003C\u002Fcode> or \u003Ccode>frontier\u003C\u002Fcode> only when you can say what the cheapest tier\ncannot do for this task, such as following a long skill without skipping a step, and write that reason at the top of\nthe skill, where a reviewer reads it. Every clone runs up to the tier you choose, or lower where the cloning\nenterprise's caps set a lower tier, and pays for it. See\n\u003Ca href=\"\u002Fdocs\u002Fcontrol\u002Fspend#model-tiers\">Model tiers\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Mistake:\u003C\u002Fstrong> A task that sorts receipts into expense categories is set to \u003Ccode>frontier\u003C\u002Fcode> because its first draft failed\non \u003Ccode>economical\u003C\u002Fcode>. The draft failed because the skill never said what the categories were, which no tier can guess.\nOnce it reads them from memory the cheapest tier sorts them, but every clone still runs a frontier model to do it.\u003C\u002Fp>\n\u003Ch2 id=\"checklist\">Checklist\u003C\u002Fh2>\n\u003Cp>Run it against the task's current version before you publish it to the Catalog. Every answer should be yes; a no is\na change to make first.\u003C\u002Fp>\n\u003Col>\n\u003Cli>Are the goal, success metric, guardrails, skill, inputs, tools and successors free of any enterprise, person, domain or repository name?\u003C\u002Fli>\n\u003Cli>Are they also free of file paths and fixed dates?\u003C\u002Fli>\n\u003Cli>Is every value an enterprise would change read from an input or from memory, and never written into the skill?\u003C\u002Fli>\n\u003Cli>Does each input have a label that says what to put in, and a default only where any enterprise could use it?\u003C\u002Fli>\n\u003Cli>Does the skill say what it asks memory for, and what it does when memory has no answer?\u003C\u002Fli>\n\u003Cli>Does the skill say what it trains to memory, as facts and outcomes only, one note per outcome?\u003C\u002Fli>\n\u003Cli>Does the skill correct a wrong note with a correction that replaces it, never a second note beside it?\u003C\u002Fli>\n\u003Cli>Does every tool that sends, publishes, spends or changes something outside the OS have a gate?\u003C\u002Fli>\n\u003Cli>Is every tool listed by its exact name, with no whole vendor and nothing the skill does not call?\u003C\u002Fli>\n\u003Cli>Does the skill call its tools by the names the task lists?\u003C\u002Fli>\n\u003Cli>Does every outcome the skill can end on lead to a successor rule, or end the work on purpose?\u003C\u002Fli>\n\u003Cli>Does the skill name each successor's slug beside the outcome that leads to it, with a line on what that task does?\u003C\u002Fli>\n\u003Cli>Does \u003Cstrong>Finishes the work on\u003C\u002Fstrong> list every outcome that ends the work?\u003C\u002Fli>\n\u003Cli>Is the success metric a number any enterprise that clones the task can count?\u003C\u002Fli>\n\u003Cli>Does the task name a model tier rather than an exact model?\u003C\u002Fli>\n\u003Cli>If that tier is above \u003Ccode>economical\u003C\u002Fcode>, does the skill say what the cheapest tier cannot do for it?\u003C\u002Fli>\n\u003C\u002Fol>\n",[12,16,20,23,26,29,32,35,38,41,44],{"id":13,"text":14,"level":15,"planned":8},"rules","Rules",2,{"id":17,"text":18,"level":19,"planned":8},"name-no-enterprise-person-domain-repository-path-or-date","Name no enterprise, person, domain, repository, path or date",3,{"id":21,"text":22,"level":19,"planned":8},"read-what-varies-from-memory-or-an-input","Read what varies from memory or an input",{"id":24,"text":25,"level":19,"planned":8},"state-what-it-reads-from-memory-and-what-it-writes","State what it reads from memory and what it writes",{"id":27,"text":28,"level":19,"planned":8},"put-a-gate-on-every-tool-that-acts-outside-the-os","Put a gate on every tool that acts outside the OS",{"id":30,"text":31,"level":19,"planned":8},"name-its-tools-exactly","Name its tools exactly",{"id":33,"text":34,"level":19,"planned":8},"name-its-outcomes-and-where-each-leads","Name its outcomes and where each leads",{"id":36,"text":37,"level":19,"planned":8},"state-its-finish","State its finish",{"id":39,"text":40,"level":19,"planned":8},"state-its-kpis","State its KPIs",{"id":42,"text":43,"level":19,"planned":8},"choose-a-model-tier-and-say-what-the-cheapest-cannot-do","Choose a model tier, and say what the cheapest cannot do",{"id":45,"text":46,"level":15,"planned":8},"checklist","Checklist",1791845663970]