Run teamai's own features as default workflows

Open
#1,589 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript
Domain
cli, devtools

Research direction

Start by reading docs/dev/workflow-engine.md and docs/guide/workflow.md, then compare the candidate table with the related decisions in #1383 and #1389. Record each candidate's outcome as a migration sub-issue or a decision to keep it on the launcher, with the reason; migrations themselves are explicitly out of scope here.

Written by the indexing model from the issue text.

Description

Example

Benchmarks (#1180) are the first teamai feature built this way. Before #1379, a suite was compiled into a run behind a flag, and the engine and the local driver carried benchmark code. After it, a suite is a shipped default workflow plus a domain command:

before                                             after
teamai workflow start <suite> --benchmark          teamai benchmark run <suite>
├─ compilePlan, in the engine's start path         └─ workflow start teamai-benchmark --inputs '{"suite":"<suite>","aliases":"team"}'   (local driver by default)
├─ RunState.benchmark, read across the engine         ├─ plan     command: teamai benchmark plan
├─ a Trials next/report wrapper                       ├─ trials   workflow: { from: plan }
└─ driveBenchmarkRun, a second local-driver loop      └─ finally: report   command: teamai benchmark report
# workflows/teamai-benchmark.yaml, shipped in the npm package; a team file of the same name overrides it
schemaVersion: v1alpha1
name: teamai-benchmark
description: Run a benchmark suite. Every arm works the same tasks in fresh clones, judged by checks it never sees.
invoke: deny
inputs: { suite: string, aliases: string }
steps:
  - id: plan
    command: teamai benchmark plan "$SUITE" --aliases "$ALIASES"
    env: { SUITE: "{{ inputs.suite }}", ALIASES: "{{ inputs.aliases }}" }
    output: { definition: workflow, plan: json }
  - id: trials
    needs: [plan]
    workflow: { from: plan }
    requires: { isolation: sandbox, strict: true }
finally:
  - id: report
    command: teamai benchmark report
    output: { text: string, table: json }
outputs: { text: steps.report.outputs.text, table: steps.report.outputs.table }

Every driver (local, skill, Paseo #1087, T3, a future plugin) works it through next and report, and none of them knows it is a benchmark.

The rule

  • Workflows are teamai's only orchestration, and drivers are its only execution system. One way to do each thing, so each has one place to maintain.
  • A feature that orchestrates AI work is a default workflow in workflows/ plus domain verbs (teamai <feature> <verb>) its command steps call. The feature's code lives in its own module and uses only the public interface of src/workflow/. The engine, the protocol and the drivers never import a feature module; workflow-module-boundaries.test.ts enforces it for src/benchmark/.
  • No breaking change. A migrated command keeps its name, flags and output, runs its workflow on the local driver by default, and takes --driver <x> to run it elsewhere.
  • What the engine lacks becomes a generic key any workflow can use, never a feature-specific branch.

The benchmark migration added these generic keys, which a later migration can reuse:

Key What it gives any workflow
workflow: { from: <step> } Runs a workflow a command step printed, instead of a nested workflow start (refused nested_workflow)
output types workflow and json A step's output can be a workflow to admit, or opaque data passed on whole
finally: and done.outputs Read-only command steps that run however the run ended; the run's outputs reach every driver
workflow start --timeout A run deadline shorter than the definition's
workspace: { clone } A fresh clone at a commit, prepared by teamai, with the team installed at a chosen revision
tool:, model: { name, effort } A step pinned to a tool and an exact model, leased only to a driver that runs it
on_limit: end_turn A limit that ends the agent's turn and keeps its work, instead of failing the step
requires: { …, strict: true } Isolation and network that must be met, with credentials withheld
scorers: { sampling: all } Every pass judged
Isolated run A run that opens a clone is never published, claimed or retried, and counts in no stats
The running CLI on a step's PATH A command step that runs teamai … gets the CLI that runs the step, so a domain verb never meets another installed version

Candidates

Every AI caller below goes through the launcher (#1389) today. None is a workflow yet. #1383 and #1389 chose the launcher for import, codebase, recall promote and ci extract-mr; this issue keeps that choice until a candidate's blocker is cleared, and records the blockers in one place.

Feature Today Known blocker Source
teamai ci extract-mr importFromMR, then importLocalCheckout (src/ci/extract-mr.ts:14, :200-201) Must run in a bare CI checkout with no teamai init. A team can already wrap it in its own workflow, as #1389's mr-learnings example does #1389 Out of scope; #1383 Out of scope
teamai recall promote Two AI calls in src/maintenance/promote.ts (:204, :315) Promotion writes the team repo, and a command step that writes the checkout fails read_only_dirty in self mode. The candidate list is also built for teamai dashboard (src/viz.ts:467), which is not a run #1389 Out of scope and Notes
teamai import (repo, local, iwiki, --from-mr) callToolParallel (src/import-local.ts:301); writes drafts into the team repo (:548) The same write as promotion, so the same read_only_dirty in self mode: not yet confirmed by a run. --from-mr is also reached from ci extract-mr in a bare checkout #1389 caller table
teamai codebase --deep-enrich Parallel batches of 5 (src/deep-enrich.ts:439, :455); writes generated pages (:108) Reached from ci extract-mr in a bare checkout. Its batches run in parallel today; a workflow runs parallel prompts only up to workflows.max_parallel, 1 unless set #1389 caller table and criteria
enrich-with-ai callToolParallel (src/enrich-with-ai.ts:221, :247), from codebase extraction (src/codebase-extract.ts:1044) Reached from ci extract-mr in a bare checkout, through importLocalCheckout #1389 criteria
teamai recall maintenance --update-quality One AI call per stale entry (src/maintenance/quality-update.ts:213); suggests updates None recorded —
votes-judge Opt-in Stop hook with TEAMAI_UPVOTE_JUDGE=1, on every Stop (src/hook-handlers.ts:811, :1305) #1391 is open on whether it becomes a session scorer or stays on the launcher. A run per Stop also costs latency #1391 already weighs #1391
teamai score --session Standalone; returns a WorkflowEnvelope and the same lease format (src/session-flow/scoring.ts:252). teamai-share-session already calls it as a command step Its subject is a session; workflow scorers judge step passes. A judge is never judged #1383 Decisions; workflows/teamai-share-session.yaml

Blockers that cut across candidates:

nested_workflow       a command step cannot start or drive another run (src/workflow/attempt-marker.ts:66-72)
                      → compose with a workflow step, or workflow: { from } as benchmarks do
read_only_dirty       a command step with no workspace may not change the checkout
                      → open: a place for steps that write the team repo in self mode
bare checkout         ci extract-mr runs with no teamai init
                      → open: whether a default workflow can start there
describe proposals    proposed inputs are coded per workflow (SessionShare.proposals returns {} for non-share names,
                      src/session-share.ts:240) → each default with proposed inputs needs its own, or a shared seam
definition_mismatch   another machine claims a default run only with the same shipped bytes

Acceptance criteria

  • Every candidate above ends in one of two states, each recorded on this issue: a sub-issue that migrates it to a default workflow plus domain verbs, or a decision to keep it on the launcher, with the reason.
  • A migrated command keeps its name, flags and output, runs on the local driver by default, and takes --driver.
  • A migration adds no feature-specific branch to the engine, the protocol or a driver; the boundary test covers the new feature module.
  • A blocker shared by several candidates (read_only_dirty in self mode, the bare checkout) is solved once, as a generic key or rule, before the candidates that need it.

Definition of done

  • docs/dev/workflow-engine.md records the rule and the pattern (added by #1379), and names each migrated feature.
  • docs/guide/workflow.md and its zh-CN page list each new default workflow, as they list teamai-share-learnings, teamai-share-session and teamai-benchmark.
  • #1383's Out of scope line about import, codebase, recall promote and ci extract-mr points here.

Blocked by

Blocked by #1379

Out of scope

  • Changing what any command does, or its flags and output.
  • Triggers, schedules or webhooks inside teamai (#1383).
  • The launcher itself (#1389).
  • Migrating a candidate in this issue. Each migration is its own issue.

Related

  • #1180, #1379: the first migration.
  • #1383, #1389: the launcher decision this issue revisits candidate by candidate.
  • #1388: default workflows a team can override; teamai-share-learnings and teamai-share-session.
  • #1402: teamai-session-to-task, the next planned default workflow.
  • #1391: votes-judge.
  • #818: the workflow runtime.
Dominant language
TypeScript
Stars
5.7k
Forks
486
Avg merge
16h 48m
Merged PRs (30d)
422

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Tencent/teamai-cli

All issues in Tencent/teamai-cli

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.