Repository navigation
feat(workflow): add HITL steps and manual run controls - #1205
Conversation
Testing evidence is sufficient: the description records a build and representative real-CLI E2E runs. I only read the scoped diff; nothing from the PR was run, built, or installed. |
|
Fixed in 5a48151. A HITL request in the retry cone that is waiting, or answered and not yet run, now starts a new pass: the dependent approval is asked again in the new context, and an answer to the old pass gets |
Earlier finding resolved: dependent HITL answers are cleared and waiting requests advance their passes on retry. Testing evidence is sufficient: the description records a build and representative real-CLI E2E runs. I only read the scoped diff; nothing from the PR was run, built, or installed. |
|
Fixed in f15b628. Commands that are still exiting after a cancel now take a slot in the local driver, so a retried step starts its new pass only after the cancelled attempt has exited, at any |
Earlier HITL invalidation finding resolved: dependent answers are cleared and replacement requests advance their passes. The command-overlap finding is only partially fixed, as described above. Testing evidence is sufficient: the description records a build and representative real-CLI E2E runs. I only read the scoped diff; nothing from the PR was run, built, or installed. |
|
Fixed in 9fe51cc. A held lease now waits while an attempt of its own step is still exiting, so a retried command never starts beside its cancelled attempt at any The earlier Ubuntu failure was that test hitting its 15 s timeout. It now runs the command through |
|
No new findings in the scoped diff. Earlier findings are resolved:
Testing evidence is sufficient: the PR description records a build and representative real-CLI E2E runs. Deferred provider and agent coverage is not blocking. I only read the scoped diff; nothing from the PR was run, built, or installed. |
|
No new findings in the scoped diff. Earlier findings are resolved:
Testing evidence is sufficient: the PR description records a build and representative real-CLI E2E runs. Deferred provider and agent coverage is not blocking. I only read the scoped diff and trusted base review rules; nothing from the PR was run, built, or installed. |
d99cdd0 to
3659a18
Compare
|
No new findings in the scoped diff. Earlier findings are resolved:
Testing evidence is sufficient: the PR description records a build and representative real-CLI E2E runs. Deferred provider and agent coverage is not blocking. I only read the scoped diff and trusted base review rules; nothing from the PR was run, built, or installed. |
A workflow step can now ask a person: `approve` (yes or no, `required` for answers that must come from a person), `choose` (options with an optional default, readable as `steps.<id>.choice` and `.note`), or `interactive: true` (a person works in the tool). `next` returns a `hitl` request to a driver that declares `driver.can.hitl`; a driver without HITL gets the auto-approve table or `hitl_required`. New `teamai workflow respond`, `retry`, `cancel` and `resume` change a run by hand. Retry reopens a step and what depends on it as a new pass, reopens a settled run, replaces its published end and stats, and prints the `resume` command when the run needs a driver again. Cancel stops open work and invalidates its leases. A driver with its own UI answers through `respond --json` with channel `driver`. The local driver asks HITL requests on its terminal while it polls for answers from other processes, gives the terminal to interactive tools, stops cancelled tools and every process a cancelled command started, starts a retried step only after its cancelled attempt has exited, and holds one driver lock per run. Closes Tencent#1081
3659a18 to
1c183af
Compare
|
No new findings in the scoped diff. Earlier findings are resolved:
Testing evidence is sufficient: the PR description records a build and representative real-CLI E2E runs. Provider and agent coverage deferred to CI is not blocking. I only read the scoped diff and trusted base review rules; nothing from the PR was run, built, or installed. |
Summary
Workflows can now put a person in the loop (HITL), and a person can fix a run by hand. Closes #1081.
How
nexttreats a HITL request:interactivedriver.can.hitlhitlrequesthitlrequesthitlrequestauto_approveyeshitl_requiredhitl_requiredhitl_requiredno, step skippedhitl_requiredhitl_requiredhitl_requiredWho can answer a
requiredrequest:respondfrom a TTY (channeltty), or a driver's own UI withrespond --json(channeldriver). Without a TTY,respondis channelcliand answers optional requests only.What a manual control changes:
The local driver asks HITL requests on its terminal and polls in the background, so an answer from another process closes the question. An interactive tool gets the terminal. Ctrl-C goes to the tool, as with
teamai env exec. One local driver runs a run at a time.Evidence
main,teamai workflow respond|retry|cancel|resumedo not exist. A step can't ask a person, and a stopped run can only be started again from the beginning.After: the built CLI, run as separate processes for each command (
npm run build && npm run test:e2e -- src/__tests__/e2e/workflow-run-controls.test.ts src/__tests__/e2e/workflow-conformance.test.ts src/__tests__/e2e/workflow-signals.test.ts):Also passing:
npx tsc --noEmit,npm run lint, andnpx vitest run(11,191 passed, 21 skipped as onmain). A table ofretryandcancelfrom every step state (pending with an answer, waiting, leased, running, failed, cancelled, refused approve, answered choose) checks that no HITL answer outlives its pass, and that real commands atmax_parallel1 and 2 never run two attempts of one step at once, also when the shell cannotexecinto the command (node work.js; true). A queued end that a retry replaces while an earlier end is being dequeued stays queued (the dequeue now holds the run lock). The advertisedrespondcommand quotes fan-out step paths such as'items[0].ask'and runs as printed in zsh.retryof a reopened run returnsresume: "teamai workflow resume <run>". A real-CLIcancelofsh -c 'sleep 30 & wait'atmax_parallel: 1leaves nosleepinps, and the command can still read/dev/tty.commands.mdwas regenerated withnpx vitest run commands-reference -u.The new terminal test drives the built CLI in a pseudo-terminal with a fake tool that survives Ctrl-C. It goes red when the driver handles the terminal's Ctrl-C itself during an interactive step (the driver exits), and when the driver opens the HITL question while the tool runs.
A manual run of the same workflow with Claude Code as the interactive tool showed Ctrl-C reaching Claude ("Press Ctrl-C again to exit") with the driver still running. Codex and OpenCode TUIs, Windows
taskkill, and the extra providers and agents are left to CI.Merge Danger
Door: two-way
The new YAML keys, commands, and the
hitlanswer are additive. Run files and records written before this change still read: every new field is optional. External drivers that know nothing about HITL keep working. A HITL step is answered for them by the table above, and the guides describe the contract for drivers that want HITL.Blast Radius: workflows
cancelcan stop the whole tool. A terminal Ctrl-C reaches the tool through the driver, which stops it with SIGTERM.max_parallel: 1command stays in the terminal, so it keeps Ctrl-C and/dev/tty. The driver stops it together with every process it started, taken from onepssnapshot. SIGKILL goes only to captured processes whose start time still matches, so a reused PID is spared;lstarthas one-second resolution, so this narrows that window rather than closing it. A process that daemonizes out of that tree is not reached. Withoutps, it stops the shell alone, as onmain.interactivekeep the repository changes the person makes. Headless prompts keep the read-only check.stats/<user>.yamlreplace the first one instead of counting another run.