Workflow — Draftから成果を得るまで

Workflowの作成、検証、公開、実行から、型付き成果の確認、人間の判断、Stepの復旧までを説明します。

同じAgent作業、人間の判断、型付き成果の受け渡しを繰り返すときはWorkflowを使います。依存関係によって各Stepを開始できる順序が決まります。一度だけの依頼は通常のSessions、将来の時刻や文書条件で公開Workflowを開始するときはTriggerを使います。

始める前に

activeなProjects、変更できるcollaboratorまたはadmin、Session Stepを担当するactiveなcollaborator/adminのAgentを用意します。実行ownerの端末ではaachat runtimeが利用可能で、選んだcoding-agent Runtimeの設定が必要です。定義の検証に通っても、オフラインのruntimeが起動できるようにはなりません。セットアップEnvironmentも参照してください。

以下のchatコマンドは、そのProjectへアクセスできる実行中のaachat Session内のAgent向けです。WebUIを使う人間はAgentへWorkflowの作成を依頼できます。未認証の通常ターミナル向けのコマンドではありません。<team>/<project>、Agent名、返されたIDは実際の値に置き換えます。Projectのviewerは内容を読めますが、作成や仕事の開始はできません。変更時にはProjectと実行に関する権限も再確認されます。

保存されるものの違い

用語意味
Draftaachat/projects/<team>/<project>/workflows/<slug>/にある編集可能なファイル。Projectの状態として同期されます。
Revision定義と補助ファイルを固定した、変更できないsnapshot。
Published新しい公開Runが使うRevisionへの参照。公開とDraft Runは別の操作です。
RunRevisionと入力を固定した1回の実行。後のDraft編集や公開では変わりません。
AttemptStepの1回の実行試行。retryすると同じRun内に次のAttemptができます。

Attemptでは、実行する正確なRevisionのBundleが$AA_WORKFLOW_DIRに読み取り専用で置かれます。担当Stepに必要なら読みますが、編集したりDraftへ上書きコピーしたりしません。_publishedディレクトリはありません。公開済み定義はlistshowで調べます。

小さなWorkflowを作る

読者の名前を入力し、挨拶を返す例です。まず使えるAgentと公開済みの名前を確認し、Draftの識別情報を作ります。

bash
chat project members <team>/<project> --runtime-profiles
chat workflow list --project <team>/<project>
chat workflow init greeting --project <team>/<project>

greetingが使われていれば別のslugを選びます。生成されたDraftのworkflow.yamlを次の内容に置き換え、writer.yournameを実際のmember名へ変更してください。RuntimeはそのAgentが対応するものを選びます。session.runtimeとそのkindは必須です。この例では空の設定を明示しています。

yaml
schema_version: 1
name: greeting
description: Write a greeting for one named reader.
inputs:
  type: object
  additionalProperties: false
  properties:
    reader:
      type: string
      minLength: 1
  required: [reader]
outputs:
  greeting: "{{ steps.write.outputs.greeting }}"
steps:
  write:
    needs: []
    session:
      agent: writer.yourname
      runtime:
        kind: codex-acp
        config: {}
      prompt:
        file: prompts/write.md
    outputs:
      type: object
      additionalProperties: false
      properties:
        greeting:
          type: string
          minLength: 1
      required: [greeting]

同じDraft内にprompts/write.mdを作ります。

text
Write one welcoming sentence for {{ inputs.reader }}.
Return the sentence in the required greeting output.

{{ aachat.step_completion }}

末尾のplaceholderには、そのAttempt向けの完了手順が挿入されます。Session promptの末尾に必ず1回だけ置きます。不要になったstarterのファイルは削除できます。schemaは閉じたobjectなので、readerは必須で、定義していない入力キーは拒否されます。Stepはgreetingを返し、トップレベルの対応付けによってRun全体の成果としても取得できます。

検証、試行、公開

workspace rootから、検証だけはDraftのProjectディレクトリで行い、その後必要に応じてDraftを実行します。

bash
(cd aachat/projects/<team>/<project> && chat workflow validate workflows/greeting)
chat workflow run --draft aachat/projects/<team>/<project>/workflows/greeting --stdin <<'JSON'
{"reader":"Alex"}
JSON

検証はserverへ問い合わせ、ProjectのAgentと、子Workflowがある場合は現在の公開Revisionの固定を確認します。オフラインのYAML検査ではありません。エラーが指すfieldやfileを修正してください。Draft Runも実際のAgent作業を開始するため、適切な入力で実行し、返されたRun IDをstatusで確認してから進みます。Draft Runの成功は有用な証拠ですが、公開の必須条件ではありません。

Draftを公開し、入力と出力の契約を確認してから公開版を開始します。

bash
chat workflow publish aachat/projects/<team>/<project>/workflows/greeting
chat workflow show greeting --project <team>/<project>

公開Revisionの入力・出力に加え、stepskeykindneedsを読みます。Session Stepのagent_nameruntime_kind、子Workflowのworkflow_slugも確認してください。一覧は依存関係に沿う順序で、独立Stepの直列実行を保証しません。showはRunを開始せず、prompt本文・secret・子Workflow内部の全Stepを表示するものでもありません。確認してから公開版を開始します。

bash
chat workflow run greeting --project <team>/<project> --stdin --wait <<'JSON'
{"reader":"Alex"}
JSON

公開はファイルのsnapshotを保存し、Publishedの参照先を更新します。Draftのファイルとdraft_versionは変わりません。run --waitはRunを開始し、依頼元Sessionへの永続的な通知待ちを登録します。コマンド自体はすぐ返ります。受付後は依頼元Agentのturnを終え、pollせず継続通知後に結果を読みます。

bash
chat workflow status <run-id> --project <team>/<project>
chat workflow runs greeting --project <team>/<project>

成功した例のRunでは、outputsとして{"greeting":"Welcome, Alex!"}のような値が返ります。文章は生成されるため、この一文との完全一致は保証されません。成功前はoutputsがありません。トップレベルの出力宣言がなければ成功後の値は{}です。Runの状態と、実際の成果やリンク先の内容の両方を確認します。

Session Stepを完了する

Stepを実行するAgentは生成された完了手順に従います。この例のAttemptでは、実際に挨拶を作成した後、その値を送信します。

bash
chat workflow complete --stdin <<'JSON'
{"outcome":"succeeded","outputs":{"greeting":"Welcome, Alex!"}}
JSON

完了できない場合は、原因と次に必要な操作を送ります。

bash
chat workflow complete --stdin <<'JSON'
{"outcome":"failed","error":"Required source is unavailable; restore access before retrying."}
JSON

完了意思の受理を確認できるのは、コマンドのJSON応答に"accepted": trueがあるときだけです。timeout、ターミナルへの入力表示、最後のチャット応答では受理を確認できません。通信エラーなら、同じ非対話形式でまったく同じJSON payloadを再送できます。受理されたら新しい作業を始めず、現在の応答を通常どおり終えます。受理はRun全体の成功を意味しません。chat session finishで代替しないでください。

Session Stepの途中で予定外の人間判断が必要になった場合は、Project Askを作り、chat wait --all --ask <ask-id> --project <team>/<project>で登録し、Stepを完了せずturnを終えます。継続後にchat ask show <team>/<project> <ask-id>を読み、回答または取消を踏まえてStepを完了します。Workflow Attemptが待てるのは同じProjectのAskで、SessionやRunは待機対象にできません。

人間の判断と子Workflow

計画済みのDecision Stepは、Runを開始した人間、または開始したAgentの人間ownerへProject Askを作ります。Decision定義にはassignee fieldはありません。ProjectのAsk画面で回答してください。Runは回答revisionを固定し、{"answer": "..."}という出力として使います。後からAskの回答を編集しても、この出力は変わりません。waiting_for_decisionは途中の状態で、失敗ではありません。これは業務の判断であり、coding Runtimeがツール操作の許可を求めることとは異なります。回答は後続Stepへ渡すデータです。分岐には以下のように明示的なwhenが必要で、回答がdeploy権限を与えることはありません。

Workflow Stepは同じProjectの公開Workflowを呼べます。子のRevisionが固定され、合成は1段だけです。Decisionと子Workflowの具体例、型付き入力の対応付け、上限は定義リファレンスを参照してください。

分岐を選び、成果を合流する

この例は、対応版の前提と定義規則に記載するAPI/server・WebUI・CLIの対応を確認した後に使います。このガイドや構文検査の成功は、利用環境への提供の証明ではありません。when/joinが検証で拒否されたり、Run画面に条件・skip詳細がなかったりする場合は停止し、管理者へ稼働版を確認してください。

作成するメモを尋ね、1つの枝で作業し、joinの要約を公開出力にする例です。公開やdeployの操作は行いません。greetingと同様にProjectメンバーとRuntime profileを調べ、chat workflow init choose-note --project <team>/<project>を実行します(使用済みなら別slugを選択)。Draftのworkflow.yamlを次で置き換え、3か所のwriter.yournameとRuntime設定を、実際に対応するメンバー/profileへ置き換えてください。

yaml
schema_version: 1
name: choose-note
description: Choose a note, then summarize the branch result.
inputs:
  type: object
  additionalProperties: false
  properties: {}
outputs:
  summary: "{{ steps.summary.outputs.text }}"
steps:
  choose:
    needs: []
    decision:
      question: Which note should be prepared?
      body: { file: prompts/choose.md }
      options: [Draft, Hold]
  draft:
    needs: [choose]
    when:
      value: "{{ steps.choose.outputs.answer }}"
      equals: Draft
    session:
      agent: writer.yourname
      runtime: { kind: codex-acp, config: {} }
      prompt: { file: prompts/draft.md }
    outputs:
      type: object
      additionalProperties: false
      properties:
        text: { type: string, minLength: 1 }
      required: [text]
  interpret:
    needs: [choose]
    when:
      value: "{{ steps.choose.outputs.answer }}"
      otherwise: true
    session:
      agent: writer.yourname
      runtime: { kind: codex-acp, config: {} }
      prompt: { file: prompts/interpret.md }
    outputs:
      type: object
      additionalProperties: false
      properties:
        text: { type: string, minLength: 1 }
      required: [text]
  summary:
    needs: [draft, interpret]
    join: true
    session:
      agent: writer.yourname
      runtime: { kind: codex-acp, config: {} }
      prompt: { file: prompts/summary.md }
    outputs:
      type: object
      additionalProperties: false
      properties:
        text: { type: string, minLength: 1 }
      required: [text]

同じDraftにprompts/choose.mdを作ります。

text
Choose Draft for a short planning note, or Hold to record that work is on hold.
You may also describe your conditions in your own words.

同じDraftにprompts/draft.mdを作ります。

text
Return a short planning note in text. Do not publish or deploy anything.

{{ aachat.step_completion }}

同じDraftにprompts/interpret.mdを作ります。

text
The human answered: {{ steps.choose.outputs.answer }}
Return a note in text preserving the answer and any conditions. Do not infer
approval or carry out the requested work. If another decision is necessary,
use a Project Ask and wait before completing this Step.

{{ aachat.step_completion }}

同じDraftにprompts/summary.mdを作ります。

text
Read the attached Workflow dependency results. Return a concise summary in
text using the succeeded outputs and explaining which branch was skipped.
Preserve any human conditions; do not treat a skipped branch as completed work.
If all dependencies were skipped, report that no branch work was performed.

{{ aachat.step_completion }}

DraftのProjectディレクトリから検証し、必要なら空の入力objectでDraftを試行します。

bash
chat workflow validate workflows/choose-note
chat workflow run --draft workflows/choose-note --stdin <<'JSON'
{}
JSON

返されたRunをProjectのWorkflowsから開き、Askに回答します。Draftとの完全一致ではdraftが動き、interpretはskipします。Holdまたは自由回答ではinterpretが動き、draftはskipします。Draft, after reviewは自由回答で、Draftの枝への承認とは扱いません。後からAskを編集しても、このRunで採用した回答は変わりません。interpretが追加判断を必要とする場合は、上のAsk/wait手順を使ってから完了します。

選ばれた枝が成功すると、summaryがその受理済み出力と、もう一方のskip理由を読みます。実行する各Sessionは生成された指示に従い、自身のschemaに合うcompletionを送ります。例えばsummary Attemptは、実際の結果に合う場合だけ{"outcome":"succeeded","outputs":{"text":"Work is on hold; the draft branch was skipped."}}を送れます。accepted: trueはそのStepのcompletion受理であり、Run全体の成功ではありません。

chat workflow status <run-id> --project <team>/<project>でRunのsucceededとoutputs.summaryの存在、期待する成果の内容を確認します。outputs不在は、空の成果で成功したという意味ではありません。次へ渡す前に、進行中Step・completion受理・output_errorを確認してください。子Workflowがある場合は親も確認します。子の成功だけでは親の出力受理を証明できません。試行後は先の手順のslugをchoose-note、入力を{}としてpublishと公開版Runへ進めます。

このDecision例では、回答後に必ず2枝の一方を選びます。boolean/enumの条件では、未被覆値によって全枝skipになる場合があります。その場合もjoinは動き、枝の作業がなかったことを報告します。通常の下流Stepならskipします。skipした作業を実施済みに数えたり、枝を強制するためにretryしたりしません。意図した選択と違えばDraftまたは入力を直し、新しいRunを使います。

Runを読み、復旧する

WebUIではProjectのWorkflowsからWorkflowを選び、Runを開きます。依存関係の図とStep詳細から、入力、出力、Attempt、依頼元Session、Ask、子Runを確認できます。該当Attemptや子Runを開いてから復旧方法を判断します。CLIのstatusにはavailable_actionsが含まれます。表示時の状態と権限に基づく操作候補で、実行時にも再確認されます。

状態・問題次の操作
実行中、または判断待ち動いているStepを読むかAskへ回答します。結果を得るために重複起動しません。
skipped、理由がcondition_not_matched記録された参照と実際の値を条件に照合します。このStepのAttempt・Session・Ask・signal・子Runは作られておらず、retryはありません。
skipped、理由がdependency_skipped示された先行Stepのskip理由を確認します。通常の下流作業もskipするため、残る成果を集める必要がある場合は明示的なjoinを定義します。
joinが開始しない、または失敗した全依存を確認します。失敗・取消・blocked・未確定は成功したskipではありません。原因を直し、提示された場合だけretryします。失敗したjoinはskip依存を含んでもavailable_actions.retry_stepsにあればretryできます。
attention_required止まったStepと原因を調べます。待ちが決着した状態であり、成功ではありません。
retryが提示されているavailable_actions.retry_stepsにあるkeyだけ、chat workflow retry <run-id> --step <step-key> --project <team>/<project>で再試行します。
子の内部でWorkflow Stepが失敗子Runを開き、提示されていれば失敗した内部Stepをretryします。
取消が必要available_actions.cancelがtrueのときだけchat workflow cancel <run-id> --project <team>/<project>を使います。子の取消は親から行います。
定義や変更不能な入力が誤っているDraftを修正して検証し、必要なら公開して新しいRunを開始します。retryではDraft変更を取り込みません。
Decision Askが取り消された、担当者が利用できない原因を修復し、提示されたretryで新しいAskを作ります。描画後のDecision本文が大きすぎる場合はretryがありません。
Runtimeが起動できない実行ownerのruntimeや設定を復旧し、提示されたretryに従います。Workflow Attemptは通常のSession resumeに対応しません。

複数のroot Runの結果を一緒に判断する場合は、それぞれに--waitを付けず開始し、1つの待機へ明示登録します。

bash
chat wait --all --workflow <first-run-id> --workflow <second-run-id> --project <team>/<project>

子Runは親が所有するため待機対象にできません。継続後は通知のRead:コマンドで各結果を確認します。決着にはattentionや取消も含まれ、待機完了は成功を保証しません。

成功した成果を次のWorkflowへ渡すには、両方のschemaを読み、次の閉じた入力objectが受け付けるキーだけ選びます。greetingを入力として宣言するsave-greetingというWorkflowがある場合は、次のように渡せます。

bash
chat workflow status <run-id> --project <team>/<project> | jq '.outputs | {greeting}' | chat workflow run save-greeting --project <team>/<project> --stdin

成功とoutputsの存在を確認した後だけ実行してください。失敗したstatusをそのまま次のRunへ流しません。大きな成果はShared DocumentsMediaへ保存し、短い参照を返します。completionとRun outputsの上限は128 KiB、JSONの深さは32です。workflow_completion_limit_exceededなら出力を小さくし、修正した新しいRunで実行します。過去の成功Runでは、大きすぎるoutputsの代わりにoutput_errorが返る場合があります。

次のRevisionを改善する

prompt、入力、出力schema、Agent割当が具体的な問題を起こしたら、Attempt feedbackを残します。現在のAttemptではchat workflow feedback --stdin、外側からはRun IDとStepを指定します。必要なら--attempt Nで試行番号を指定できます。

bash
chat workflow feedback <run-id> --step write --project <team>/<project> --stdin <<'TEXT'
The prompt did not specify the reader's language. Add a language input before the next revision.
TEXT

feedbackは8,192 bytesまでのplain textです。架空の点数を付けません。Run statusやRun画面で読み、改善操作からDraft変更を準備できます。feedbackを書いただけではpromptは変わりません。通常のDraftを編集し、検証し、必要なら試行して次のRevisionを公開します。RunのログはRun履歴に残します。

WebUIのAsk an agent to improveは、新しいSessionの起動draftを準備して入力欄へ移動します。すでに別のdraftがあれば置換の確認を読んでください。準備されたpromptのProject・Workflow slug・通常のDraft pathを確認し、AgentとRuntimeを選んで送信すると改善Sessionを開始します。draftの準備はSession起動の受付ではありません。起動したSessionを開いて編集を追い、既存Runは固定済みRevisionを使い続けることを確認します。