Skip to content

Profiles and intents

A turn’s instructions have two parts:

  • The procedure is the mechanics of the turn: reading the pull request, delegating, the ambiguity gate, the rule that an automatic round never approves on its own, publishing, the record that ends it. It comes from the intent’s instructions, rendered for each turn with only the steps that turn runs. The bundled intents are defaults: your profile overrides any of their files, as Change a bundled intent shows. The shared partials, such as the record protocol, are files of the profile too: a partials/<name>.md.tmpl of yours replaces the bundled one for every intent, as Change a partial shows.
  • The judgment is yours: what a review looks for, the labels and what blocks, the risky surfaces, the shape of the body, the voice; how you answer reviews of your pull requests, commit and test the fixes, and whom you ask for another look; what a nudge says and its tone.

Your review profile is one directory of blocks: Markdown files whose path says when each applies. The configuration’s profile names it, either a name under ~/.config/wloop/profiles/ or a path. wloop‘s bundled guides are the layer below it: they come first, and your blocks add to them.

intent=review.md every review
organization=acme/intent=review.md reviews in acme's repositories
organization=acme/repo=api/intent=address.md address rounds in acme/api
user=dependabot[bot]/intent=review.md reviews of that author's pull requests
tags/change=refac/intent=review.md reviews whose brief tags the change a refactor

Every block that matches the pull request goes into the turn, in a fixed order, each under its own heading: wloop's review guide, then Your review guide, then Organization acme, and so on. Where two blocks disagree, the later one wins; a block with override = true drops the blocks above it on its path. The profile format has the full grammar.

The bundled guides, intent=review.md, intent=address.md and intent=nudge.md, hold every default you may want to change: what to look for, risky surfaces, Conventional Comments labels, the body and the voice of a review; the stance, commits, replies and whom to ask again in an address round; the content, tone and form of a nudge. A nudge always mentions exactly the people the pull request waits on, says what it waits for and since when, asks for one next step and posts one comment; your intent=nudge.md blocks set tone, length, language and sign-off.

Terminal window
wloop profile check # load the profile, list its intents and blocks
wloop profile show acme/api # which blocks a round in acme/api reads
wloop profile try <url> # the review your profile would publish, unpublished

An intent is a kind of turn: review, address, nudge, act, start, chat, attach, the brief, the probe, or one your profile adds. Each is a manifest, intent.toml, plus the turn’s instructions template, instructions.md.tmpl. From the manifest wloop builds:

  • a command: wloop <intent> <url> [flags] [guidance...], listed by wloop --help; an intent that serves another provider takes that provider’s unit, such as a Slack message ref (<conversation>/<ts>), a permalink or slack:<key>;
  • a way to run it by hand from any agent session: wloop instructions <intent>, or the bundled skills such as /wloop-review <url>;
  • an action on the rows of the cockpit, the terminal client and the menu bar, with its own shortcut and its summary as its tooltip.

A turn of any intent records, asks, takes answers and resumes the same way. A user intent runs only when you ask; what starts a turn on its own is a workflow whose turn.start step names the intent. A directory of your profile named as a bundled intent or workflow overrides it file by file.

Bundled intentShortcutRuns inDoes
reviewVthe review workspace, at the pull request’s headreviews someone else’s pull request and publishes the review
addressFthe author workspacetriages the reviews and failing checks of a pull request you develop
nudgeNthe pull request’s workspace, else the repository’s main checkoutasks whoever the pull request waits on for the next step, in one comment
actheadless, or a sessionresolves the open items of a unit and proposes the replies as drafts
starta fresh worktree of the repository you name, else no checkoutstarts new work on a task from its brief (wloop start)
chatthe task’s last session when it can resume, else a new onetalks with an agent about a task, when you write on its chat and no session of it is live
attachthe session it is run frommakes an agent session started outside the loop a run of a task (wloop task attach)
briefheadlesswrites a unit’s brief (see The brief)
probea workspace you namea self-test of an agent home (wloop probe)

See Add your own intent and the intent manifest.

Every text a person reads, a label, a summary, a confirmation, a view’s empty line, a notification, comes from the profile and resolves in the interface language: the configuration’s ui.locale, else the system’s preferred languages, else English. Data is never translated: titles, briefs, messages and what an agent writes show as written, and ids stay the same in every language.

A layer translates its files in a mirror under locales/<tag>/: locales/pt-BR/actions.toml holds the same keys as actions.toml, only the texts, and locales/pt-BR/workflows/<name>/text.md.tmpl replaces a whole text file. The language reference marks each key that is a text with “localized”. Each text resolves on its own, from the highest layer down (your profile, then each plugin’s layer, then the bundled one):

  1. a layer that holds the text in your language wins;
  2. a layer whose English text differs from the one below it wins with that text, so a label you rewrote reads as you wrote it in every language;
  3. a layer that holds the same English text as the one below it, as a copied file does, passes to the layer below;
  4. the bundled English text ends the walk, so a text without a translation shows in English, never as a key or empty.

With the bundled pause.label = "Pause" translated as "Pausar": no file of yours, or a copy of actions.toml that keeps "Pause", reads "Pausar"; your "Hold" reads "Hold"; your "Hold" with your own locales/pt-BR/actions.toml saying "Segurar" reads "Segurar". The rule holds per key also where a file of yours replaces another whole, such as a workflow’s workflow.toml.

A translation may use only the fields its English text uses ({{.label}}, {name}); one that names another, or a key that is no text, is a profile problem that names the file and the key, and the English text shows instead. Where a count meets a noun, a template text writes {{plural .n "one" "draft" "other" "drafts"}}, and the form follows the language’s plural rules. See Translate the interface.

wloop install installs five skills into every agent home:

SkillUse
wloop-review/wloop-review <url> [guidance] runs a review round from the session you are in
wloop-address/wloop-address <url> runs an address round from the session you are in
wloop-nudge/wloop-nudge <url> runs a nudge
wloop-profileadds a rule to your profile from a sentence such as “every PR in acme must follow xyz”
wlooplets an agent session drive the CLI: start reviews, read the status, explain what the loop is doing

In Codex the same skills run as $<skill> <url>. wloop install --print-skill <name> prints one.

The review, address and nudge skills come from one template, filled from each intent’s manifest; an intent gets one when its manifest sets skill = true, and its target is named as the intent’s provider names a unit, with the manifest’s help.target saying what it is. Every installed skill carries a marker in its front matter:

metadata:
managed-by: wloop
version: "0.1.0"
sha256: 3f1c...

sha256 is the digest of the file without that line. install replaces a skill whose marker is wloop‘s and whose digest still matches, whatever version wrote it; a skill you edited, or one without the marker, stays as it is, and install and doctor say so. uninstall removes the same unedited skills and leaves the others.