目次
コンセプト

実行モデルと保証

プログラムを実行するときにActQLが保証すること。上限のある実行、処理の配置とプッシュダウン、書き込み前のプレビュー、安全な復旧。

ActQLは、エージェントが書いたばかりのプログラムを、本物の業務データを持つシステムに対してそのまま実行するユースケースも想定しています。だからこそ、このページでは、ActQLが何を保証し、何を保証しないかをはっきりさせます。人の確認やポリシーをどこに置くべきかを考える材料にしてください。各ルールの厳密な定義は実行の仕様にあります。

ここで説明するのは、仕様で定義されている保証です。どの機能や環境でそれが実装済みかは、リファレンスの実装状況(いま動くもの)と実行時の上限(既定の上限)に別途まとめています。

TL;DR

  1. 上限のない実行はありません。処理の単位や外部への操作ごとに、始める前に有限の上限が決まり、検証されます。
  2. 業務データを意図的に変更できるのは、宣言されたEffectだけです。すべてのEffectはポリシーを通ります。
  3. Runを再開すると、すでに記録した読み取り結果、LLMの答え、Effectの結果をそのまま使います。適用済みのEffectを再送することはありません。
  4. 結果が不明な操作を、推測で成功や失敗にしません。外部システムと突き合わせ、証拠が足りなければ不明のまま残します。
  5. LLMの答えは宣言どおりの型を持ちますが、その内容が正しいことまでは保証しません。

以下は、それぞれの詳細です。

プログラム、Invocation、Run、Result

ActQLは、「宣言したもの」「1回の実行で観測したもの」「その実行の記録」「その出力」を区別します。

用語何か実行ごとに変わるか
プログラム(Program)処理の定義。読み取り、計算、Result、Effectを宣言したもの。通常はSQL/Pipeで書き、共通のプログラム表現に変換される変わらない。同じプログラムを何度でも実行できる
Invocation計算の1つの段階(Stage)への具体的な入力。パラメーターの値と、その段階で実際に読んだもの(LLMの答えを含む)。複数の段階を持つプログラムでは、1つのRunに複数のInvocationがある変わる。実行のたびに、そのとき観測したものを記録する
RunHostが残す実行の記録。受け付け、Checkpoint、送ったEffectとその結果、再開の履歴変わる。実行ごとに1つ
Resultプログラムが返す、名前付きの出力Invocationから決まる

同じInvocationからは、必ず同じResultが得られます。ただし、データを読み直せば新しいInvocationになるので、読み直したデータにこの保証は及びません。Effectを受け取った外部システムがどう振る舞うかも、保証の範囲外です。

Runの状態

Runは常に、次のいずれか1つの状態にあります。表の中の「保護された処理」とは、ポリシーの判断が必要な処理、つまり外部システムの読み書きとLLMの呼び出しのことです。

状態意味
preparing準備中。実行はまだ受け付けられていない
running実行中
waiting_checkpointCheckpointで停止中。判断が出るまで、保護された処理は動かない
resuming承認が記録され、同じRunが続きを実行している
needs_reconciliation実行そのものか、1つ以上のEffectの結果が不明で、突き合わせが必要
succeeded必要な計算が終わり、Effectの結果の集約も完了した。非同期のEffectでは、外部システムが受け付けた時点でこの状態になることがあり、その処理自体はまだ続いている場合がある
failed失敗して終了した。不明な結果は残っていない
cancelledキャンセルが要求され、停止が確認され、不明な結果が残っていない

succeeded、failed、cancelled は最終状態です。結果が不明なものが1つでも残っている間は、これらの状態にはなりません。

領域ごとの保証

CheckとPlan

  • Checkは静的に行います。名前、型、プログラムが依存する定義(Connectorの読み取り元、model task、Effectの対象)、必要になるCapabilityと権限を、Hostが公開している情報と照らし合わせます。実際にその操作を許可するかどうかは、実行時にHostがポリシーと権限から判断します。Checkでは業務データを一切読みません。
  • Planでは、プログラムが従う上限を決めます。上限を決められないプログラムは拒否されるか、「未対応」として報告されます。上限がないまま実行されることはありません。前の段階の結果に依存する上限も、それが適用される処理を始める前に確定します。
  • Checkでデータの中身まで分かるわけではありません。件数、LLMが実際に返す値、外部レコードの現在の状態は、実行してはじめて分かります。

check は、何を検査したかを報告し、データは読みません。

$ actql check churn-risk.aql
Check  ok
  Sources
    salesforce.accounts   id, description                  read
    snowflake.usage_30d   account_id, active_users, trend  read
  Model task
    model-task:churn-risk.v1   input (notes, active_users, trend) → level, reason
  Effect
    update salesforce.Account   Churn_Risk__c, Risk_Reason__c   write
  Permissions
    salesforce: accounts.read, Account.update
    snowflake:  usage_30d.read
  No data read.

間違いはここで、名前の付いた理由とともに拒否されます。

$ actql check churn-risk.aql
Check  failed
  expression_type_mismatch   line 7
    risk.value.level = 1   level is STRING, got INT64

処理の配置とプッシュダウン

コンセプトの解約リスクのプログラムは、次のように各ステップが実行されます。

Salesforceの取引先と、Snowflakeで集計済みの利用データをActQLエンジンに読み込み、JOINし、取引先ごとにINPUTの列だけをLLMに送り、型付きの答えで絞り込み、更新をプレビューして、承認後にSalesforceへ書き戻す。絞り込みと集計はSnowflakeの中で実行される。

explain は同じ配置を見せます。ここでもまだ何も読みません。各ステップについて、処理を実行するSite(Salesforce、Snowflake、手元のマシン)と、そこで計算するEngineを示します。一部の選択は、あえてRunに任せます。JOINのエンジンは届く件数で変わるので、explain は推測せず、実行時に決まると表示します。出力の例はPlanとプッシュダウンにあります。

  • プランナーは、処理の順序を入れ替えたり、まとめたり、Connectorに任せたり、別の場所で動かしたりできます。ただし、結果、並び順、失敗時の振る舞い、観測するデータの範囲、権限の境界が完全に同じ場合に限ります。
  • 外部システムにどこまで処理を任せられるかは、各Connectorが宣言したCapabilityで決まります。絞り込みができないConnectorに絞り込みを頼むことはありません。

承認とEffect

  • 業務データを意図的に変更できるのは、宣言されたEffectだけです。ただし、読み取りやLLMの呼び出しにもAPI利用料やアクセスログといった副作用はあるので、これらもポリシーを通ります。
  • Effectを適用する前に、変更内容を計算してプレビューとして保存します。プレビューの精度はConnectorによって異なります。変更前後の値まで含むもの(full_diff)と、対象と変更後の値を含むもの(targeted)です。対象を事前に特定できないEffectは宣言できません。
  • 承認の対象はそのプレビューだけです。プレビューが変わる場合は、あらためて承認が必要です。
  • 各Effectを送る直前に、ポリシーと承認をもう一度確認します。承認が無効になっていれば、送らずにRunを止めます。承認と適用の間の隙、いわゆるTOCTOU問題への対策です。
  • 承認は完了の保証ではありません。承認したEffectでも、失敗したり、結果が不明になったりすることがあります。
  • ActQLはシステムをまたぐトランザクションを提供しません。いくつかのEffectを適用したあとでRunが止まっても、適用済みのものは元に戻りません。

run は、これから行う変更を正確に示してCheckpointで止まります。

$ actql run churn-risk.aql --profile mock --stop-before commit
Run run_…
  Status      waiting_checkpoint
  Checkpoint  ckpt_…
  Effect      update  (Salesforce Account)
  Items       2
  Changes
    Acme Corp     Churn_Risk__c   low     → high
                  Risk_Reason__c  (empty) → falling usage and a competitor evaluation
    Globex Inc    Churn_Risk__c   medium  → high
                  Risk_Reason__c  (empty) → support tickets about pricing

耐障害性と、結果が不明なとき

外部システムに送った操作は、1つずつ、次のいずれか1つの結果で記録されます。

結果意味
applied外部システムが変更を確認した
accepted外部システムが処理を受け付けた。最終的に完了するか失敗するかは未確定
failed外部システムが明確に失敗を返した
unknownリクエストは送られたかもしれないが、確かな応答が得られなかった

送らなかった項目は unattempted として区別して記録します。複数の項目を持つEffectでは項目ごとに結果を記録するので、一部だけ適用された状態で終わることもあります。その場合、不明な結果がなくなった時点でRunは failed になります。

承認すると同じRunが続き、status で項目ごとの結果が見えます。

$ actql approve ckpt_…
Checkpoint ckpt_…  approved
Run run_…  resuming

$ actql status run_…
Run run_…
  Status   succeeded
  Effect   update  (Salesforce Account)   2 items
    Acme Corp     applied
    Globex Inc    applied
  • 再開や復旧をしたRunは、保持している観測結果(読んだデータ、LLMの答え、Effectの結果)をそのまま使います。適用済みのEffectを再送することはありません。再開に必要な証拠が失われていた場合も、黙ってデータを読み直して同じ実行の続きとして扱うことはしません。

  • unknown を成功とも失敗とも見なしません。Runは needs_reconciliation に移り、Runと操作の識別情報をもとに、操作の照会などConnectorごとの手順で結果を突き合わせます。証拠なしに再送することはありません。証拠が足りなければ、結果は不明のまま、見える形で残します。

    $ actql status run_…
    Run run_…
      Status   needs_reconciliation
      Effect   update  (Salesforce Account)   2 items
        Acme Corp     applied
        Globex Inc    unknown   reply lost after send; reconciling with Salesforce
  • 外部システムに同じ値が入っていても、それだけでは前の試みが成功した証拠にはなりません。別の誰かが同じ値を書いたのかもしれないからです。

  • Runのキャンセルを要求すると、新しい処理を始めなくなり、実行中の処理には停止を求めます。停止が確認され、不明な結果が残っていないと分かって、はじめて cancelled になります。不明な結果があれば、先に突き合わせが必要です。キャンセルは巻き戻しではありません。すでに送った観測や適用済みのEffectはそのまま残ります。

  • ActQLは、あらゆる外部システムについて「ちょうど1回だけ届く」ことを約束するわけではありません。約束するのは、証拠なしに再送しないこと、そして結果が不明なものを、解決するまで見える状態に置いておくことです。

LLMとINFER

  • 入力のレコードごとに結果が付きます。宣言どおりの型の値を持つ ok か、failed:timeout のように理由の付いた失敗です。
  • 理由は rate_limit、timeout、provider_error、refusal、schema_invalid、safety_rejected、truncated のいずれかです。宣言した型に合わない応答は schema_invalid になり、一部だけ型に合った値として後続に渡されることはありません。
  • 既定では、失敗したレコードも成功したレコードと一緒に返すので、どう扱うかはプログラム側で決められます。INFER のステップに ON FAILURE FAIL を付けると、部分的な結果を拒否します。1件でも非成功のレコードがあるあいだステップは公開されず、行った呼び出しは記録として残ります。失敗が既定値で置き換えられることはありません。
  • 再試行するのは、レート制限、タイムアウト、提供元のエラーといった一時的な失敗だけで、回数には上限があります。拒否や不正な応答は再試行しません。黙って再試行することもありません。
  • 件数が上限を超える場合は、LLMを1回も呼びません。
  • LLMの答えが正しいことは保証しません。間違えたときの影響が大きい場面では、ポリシーとCheckpointで人の判断を挟んでください。
  • Runは、採用した答えと、各試行の証拠を記録します。復旧時はLLMを呼び直さず、採用した答えを使います。

上限のある実行

  • 実行できるプログラムには、件数、バイト数、LLMの呼び出し、Effectなど、量に関わるものすべてに上限があります。
  • 上限を超えた処理はエラーとして失敗させます。データを黙って切り詰めたり、一部だけの結果を完全な結果として返したりすることはありません。

セキュリティとデータ

  • プログラムに認証情報は含まれません。認証情報はHostが管理し、Hostが受け付けた操作のときだけConnectorがそれを使います。
  • Connectorが宣言したCapabilityは、許可とは別です。読み取りやEffectを実行してよいかは、操作ごとに、その時点のHostのポリシーで決まります。
  • データが外部システムに出ていくのは、計画で認められた操作(LLMの呼び出し、プッシュダウンしたクエリ、Effect)を通したときだけです。
  • Runの記録には、業務データやLLMの答えが含まれることがあります。Hostはこれを非公開の証跡として保持し、Hostの保持期間の設定に従って扱います。

次に読む

Source: actql/actql/docs/concepts/execution-model.md at d904416674e4 · Edit on GitHub