Workflows: agent work that starts itself

A trigger starts one or more agent sessions on the provider and account you pick. Build the flow on a canvas, review the result, and approve anything that touches the outside world.

BeyDock3 min read

Today, every agent session starts because a person typed something. A lot of useful work is repetitive: look at a pull request, fix a broken CI run, do maintenance overnight. Workflows let an event start that work. The event can be a clock, a pull request or a CI result. Agents do the job on your own machines and subscriptions, and BeyDock acts on what comes back.

Triggers

A workflow starts from one of these:

  • manual, with inputs;
  • a schedule, either a cron expression or a time window like 23:00 to 07:00, with a time zone and a catch-up rule for runs missed while a machine was off;
  • a pull request being opened, updated or made ready for review;
  • a CI run (GitHub Actions) finishing with a result you match on;
  • a command written in a pull request comment;
  • a push.

GitHub triggers work by polling with the host's own gh login. You need no server, tunnel or open port. Pull requests from strangers and forks trigger nothing by default.

Steps

A workflow is a graph, stored as a YAML file. Steps include an agent, a shell command, GitHub actions (comment, review, status, push, open a PR), an approval, a notification, and conditions. Parallel work uses foreach and queue, which spread items across a pool of accounts and stop sending work to an account near its usage ceiling.

Each agent step is its own session and picks its own provider, account, model, effort and policy. One step can be a Claude session on one account, the next a Codex session on another. Here is a pull request review:

name: PR review
host: local
repo: ~/Repo/app
on:
  - github.pull_request: { base: main, events: [opened, synchronize], draft: false }
permissions: { review: comment }
steps:
  - id: review
    agent:
      prompt_file: .beydock/prompts/review.md
      policy: read-only
      workspace: { mode: worktree, from: "{{trigger.pr.head_sha}}" }
      output:
        schema:
          summary: string
          comments: [{ path: string, line: integer, body: string }]
  - github.review:
      body: "{{steps.review.output.summary}}"
      comments: "{{steps.review.output.comments}}"

The agent does not post the review. It returns structured output, and the engine posts it, within the permissions the workflow declares. A prompt injection hidden in a pull request cannot make the agent push, because the agent has no way to.

Every run is a session

A run is not a log file. Each agent step opens a real session with a transcript you can read, interrupt or continue by chatting. Run sessions stay out of the sidebar and sit under the run, and you can move one to the sidebar if you want it.

For each step you choose where it works: in the repo itself, in its own worktree, or in a worktree shared with later steps. By default, a step that writes gets a worktree and a step that only reads uses the checkout.

Approvals

Some actions always need a person: pushing outside the bey/* branches, merging, approving a review. A workflow that does these without an approval step before them fails validation and cannot be saved.

An approval step pauses the run and shows a card with the report and the diff. It also shows the resolved action, such as "push this branch (14 commits) to dev". Your approval is tied to that preview. If the branch moved after you approved, nothing is pushed and you are asked again. A paused run holds no slot and no quota. Runs that need you also appear in Needs attention. Notifications open the card, and approvals cannot be granted from inside the notification, because the card must show everything you approve.

Built for trust

  • Agents run with a cleaned environment: no GitHub token, no gh login, no SSH agent, and a git hook that refuses pushes.
  • Text from outside, like pull request titles, comments and CI logs, is wrapped as <untrusted> when it enters a prompt. It cannot enter a shell command's text at all, only an environment variable.
  • A repository can ship workflows in .beydock/workflows/, but they do not run until you approve that exact file, and a change asks again.
  • Pushes made by the engine under bey/* do not trigger the workflows themselves.

The canvas and the Assistant

Workflows open as a canvas: add nodes, connect them, and the YAML stays beside it as the source of truth. The same canvas shows a live run. If you would rather describe the flow, the Assistant card does it. It opens a real session in the workflow's folder and edits the YAML with small edits while you watch: its cursor floats to the card it is changing, new cards appear, changed ones glow. After each turn you can revert the changes. A workflow the Assistant writes never turns itself on.

Running on an SSH host

A workflow belongs to a host. On an SSH host the engine runs in a persistent process, so a nightly job keeps going while your laptop sleeps, and everything is replayed when you reconnect.

Where it stands

This shipped in 0.3.0 and is still in early access testing. There are no webhook triggers yet, which is why GitHub triggers poll.

Every agent. One dock.