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と実行に関する権限も再確認されます。
保存されるものの違い
| 用語 | 意味 |
|---|---|
| Draft | aachat/projects/<team>/<project>/workflows/<slug>/にある編集可能なファイル。Projectの状態として同期されます。 |
| Revision | 定義と補助ファイルを固定した、変更できないsnapshot。 |
| Published | 新しい公開Runが使うRevisionへの参照。公開とDraft Runは別の操作です。 |
| Run | Revisionと入力を固定した1回の実行。後のDraft編集や公開では変わりません。 |
| Attempt | Stepの1回の実行試行。retryすると同じRun内に次のAttemptができます。 |
Attemptでは、実行する正確なRevisionのBundleが$AA_WORKFLOW_DIRに読み取り専用で置かれます。担当Stepに必要なら読みますが、編集したりDraftへ上書きコピーしたりしません。_publishedディレクトリはありません。公開済み定義はlistとshowで調べます。
小さなWorkflowを作る
読者の名前を入力し、挨拶を返す例です。まず使えるAgentと公開済みの名前を確認し、Draftの識別情報を作ります。
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は必須です。この例では空の設定を明示しています。
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を作ります。
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を実行します。
(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を公開し、入力と出力の契約を確認してから公開版を開始します。
chat workflow publish aachat/projects/<team>/<project>/workflows/greeting
chat workflow show greeting --project <team>/<project>公開Revisionの入力・出力に加え、stepsのkey・kind・needsを読みます。Session Stepのagent_name・runtime_kind、子Workflowのworkflow_slugも確認してください。一覧は依存関係に沿う順序で、独立Stepの直列実行を保証しません。showはRunを開始せず、prompt本文・secret・子Workflow内部の全Stepを表示するものでもありません。確認してから公開版を開始します。
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せず継続通知後に結果を読みます。
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では、実際に挨拶を作成した後、その値を送信します。
chat workflow complete --stdin <<'JSON'
{"outcome":"succeeded","outputs":{"greeting":"Welcome, Alex!"}}
JSON完了できない場合は、原因と次に必要な操作を送ります。
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へ置き換えてください。
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を作ります。
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を作ります。
Return a short planning note in text. Do not publish or deploy anything.
{{ aachat.step_completion }}同じDraftにprompts/interpret.mdを作ります。
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を作ります。
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を試行します。
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つの待機へ明示登録します。
chat wait --all --workflow <first-run-id> --workflow <second-run-id> --project <team>/<project>子Runは親が所有するため待機対象にできません。継続後は通知のRead:コマンドで各結果を確認します。決着にはattentionや取消も含まれ、待機完了は成功を保証しません。
成功した成果を次のWorkflowへ渡すには、両方のschemaを読み、次の閉じた入力objectが受け付けるキーだけ選びます。greetingを入力として宣言するsave-greetingというWorkflowがある場合は、次のように渡せます。
chat workflow status <run-id> --project <team>/<project> | jq '.outputs | {greeting}' | chat workflow run save-greeting --project <team>/<project> --stdin成功とoutputsの存在を確認した後だけ実行してください。失敗したstatusをそのまま次のRunへ流しません。大きな成果はShared DocumentsやMediaへ保存し、短い参照を返します。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で試行番号を指定できます。
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.
TEXTfeedbackは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を使い続けることを確認します。